From 388c464f63a549cfbe0b7efbc176ed6e28c6ce34 Mon Sep 17 00:00:00 2001 From: marqs Date: Tue, 23 Feb 2016 01:03:50 +0200 Subject: [PATCH] Initial public release (FW 0.64) --- LICENSE | 674 + README.md | 4 + .../HAL/inc/altera_epcq_controller_mod.h | 126 + .../HAL/src/altera_epcq_controller_mod.c | 797 + .../altera_epcq_controller.sv | 611 + .../altera_epcq_controller_arb.sv | 230 + .../altera_epcq_controller_fifo.v | 176 + .../altera_epcq_controller_hw.tcl | 453 + .../altera_epcq_controller_sw.tcl | 58 + .../altera_epcq_controller_wrapper.sv.terp | 248 + .../altera_epcq_controller_wrapper_hw.tcl | 648 + .../inc/altera_epcq_controller_mod_regs.h | 260 + .../endianconverter_qsys.v | 56 + .../endianconverter_qsys_hw.tcl | 84 + .../Altera_UP_SD_Card_Avalon_Interface_hw.tcl | 159 + .../Altera_UP_SD_Card_Avalon_Interface_sw.tcl | 56 + .../Altera_UP_SD_Card_Avalon_Interface_mod.h | 166 + .../Altera_UP_SD_Card_Avalon_Interface_mod.c | 1908 ++ .../SD_Card_Interface_for_SoPC_Builder.pdf | Bin 0 -> 252601 bytes .../hdl/Altera_UP_SD_CRC16_Generator.vhd | 79 + .../hdl/Altera_UP_SD_CRC7_Generator.vhd | 76 + ...ra_UP_SD_Card_48_bit_Command_Generator.vhd | 570 + .../Altera_UP_SD_Card_Avalon_Interface.vhd | 518 + .../hdl/Altera_UP_SD_Card_Buffer.vhd | 382 + .../hdl/Altera_UP_SD_Card_Clock.vhd | 80 + .../hdl/Altera_UP_SD_Card_Control_FSM.vhd | 347 + .../hdl/Altera_UP_SD_Card_Interface.vhd | 518 + .../hdl/Altera_UP_SD_Card_Memory_Block.vhd | 296 + .../Altera_UP_SD_Card_Response_Receiver.vhd | 308 + .../hdl/Altera_UP_SD_Signal_Trigger.vhd | 57 + ip/i2c_opencores/Docs/I2C_tests.c | 99 + ip/i2c_opencores/Docs/i2c_specs.pdf | Bin 0 -> 211471 bytes ip/i2c_opencores/HAL/inc/i2c_opencores.h | 33 + ip/i2c_opencores/HAL/src/component.mk | 38 + ip/i2c_opencores/HAL/src/i2c_opencores.c | 206 + ip/i2c_opencores/i2c_master_bit_ctrl.v | 621 + ip/i2c_opencores/i2c_master_byte_ctrl.v | 382 + ip/i2c_opencores/i2c_master_defines.v | 66 + ip/i2c_opencores/i2c_master_top.v | 300 + ip/i2c_opencores/i2c_opencores.v | 72 + ip/i2c_opencores/i2c_opencores_hw.tcl | 166 + ip/i2c_opencores/i2c_opencores_sw.tcl | 56 + ip/i2c_opencores/inc/i2c_opencores_regs.h | 77 + ip/i2c_opencores/timescale.v | 2 + ip/nios2_hw_crc/HAL/doc/crc_main.c | 224 + ip/nios2_hw_crc/HAL/inc/ci_crc.h | 38 + ip/nios2_hw_crc/HAL/inc/crc.h | 109 + ip/nios2_hw_crc/HAL/src/ci_crc.c | 97 + ip/nios2_hw_crc/HAL/src/crc.c | 265 + ip/nios2_hw_crc/hdl/CRC_Component.v | 314 + ip/nios2_hw_crc/hdl/CRC_Custom_Instruction.v | 101 + ip/nios2_hw_crc/nios2_hw_crc32_hw.tcl | 116 + ip/nios2_hw_crc/nios2_hw_crc32_sw.tcl | 58 + ossc.qpf | 30 + ossc.qsf | 235 + ossc.sdc | 102 + rtl/ir_rcv.v | 168 + rtl/linebuf.qip | 6 + rtl/linebuf.v | 216 + rtl/ossc.v | 197 + rtl/pll_2x.ppf | 11 + rtl/pll_2x.qip | 6 + rtl/pll_2x.v | 320 + rtl/pll_3x.ppf | 12 + rtl/pll_3x.qip | 5 + rtl/pll_3x.v | 348 + rtl/pll_3x_lowfreq.ppf | 13 + rtl/pll_3x_lowfreq.qip | 6 + rtl/pll_3x_lowfreq.v | 376 + rtl/scanconverter.v | 682 + rtl/timescale.v | 2 + rtl/videogen.v | 150 + software/sys_controller/Makefile | 1099 ++ software/sys_controller/av_controller.c | 1393 ++ software/sys_controller/it6613/EDID.c | 196 + software/sys_controller/it6613/HDMI_COMMON.h | 11 + software/sys_controller/it6613/HDMI_TX.c | 314 + software/sys_controller/it6613/HDMI_TX.h | 29 + software/sys_controller/it6613/edid.h | 129 + software/sys_controller/it6613/hdmitx.h | 119 + software/sys_controller/it6613/hdmitx_nios2.c | 82 + software/sys_controller/it6613/it6613.c | 83 + software/sys_controller/it6613/it6613.h | 29 + software/sys_controller/it6613/it6613_drv.c | 3461 ++++ software/sys_controller/it6613/it6613_drv.h | 844 + software/sys_controller/it6613/it6613_sys.c | 550 + software/sys_controller/it6613/it6613_sys.h | 63 + software/sys_controller/it6613/typedef.h | 329 + .../mem_init/epcq_controller_0.hex | 1 + software/sys_controller/mem_init/meminit.qip | 1 + software/sys_controller/mem_init/meminit.spd | 6 + .../mem_init/sys_onchip_memory2_0.hex | 1154 ++ software/sys_controller/spi_charlcd/lcd.c | 108 + software/sys_controller/spi_charlcd/lcd.h | 39 + software/sys_controller/sysconfig.h | 34 + software/sys_controller/ths7353/ths7353.c | 81 + software/sys_controller/ths7353/ths7353.h | 63 + software/sys_controller/tvp7002/tvp7002.c | 401 + software/sys_controller/tvp7002/tvp7002.h | 90 + .../sys_controller/tvp7002/tvp7002_regs.h | 117 + software/sys_controller/tvp7002/video_modes.c | 85 + software/sys_controller/tvp7002/video_modes.h | 72 + .../sys_controller_bsp/HAL/inc/alt_types.h | 54 + .../HAL/inc/altera_nios2_gen2_irq.h | 80 + software/sys_controller_bsp/HAL/inc/io.h | 81 + software/sys_controller_bsp/HAL/inc/nios2.h | 300 + .../sys_controller_bsp/HAL/inc/os/alt_flag.h | 98 + .../sys_controller_bsp/HAL/inc/os/alt_hooks.h | 61 + .../sys_controller_bsp/HAL/inc/os/alt_sem.h | 96 + .../HAL/inc/os/alt_syscall.h | 75 + .../HAL/inc/priv/alt_alarm.h | 101 + .../HAL/inc/priv/alt_busy_sleep.h | 35 + .../HAL/inc/priv/alt_dev_llist.h | 77 + .../inc/priv/alt_exception_handler_registry.h | 39 + .../HAL/inc/priv/alt_file.h | 179 + .../HAL/inc/priv/alt_iic_isr_register.h | 39 + .../HAL/inc/priv/alt_irq_table.h | 59 + .../HAL/inc/priv/alt_legacy_irq.h | 158 + .../HAL/inc/priv/alt_no_error.h | 77 + .../HAL/inc/priv/nios2_gmon_data.h | 47 + .../HAL/inc/sys/alt_alarm.h | 126 + .../HAL/inc/sys/alt_cache.h | 117 + .../HAL/inc/sys/alt_debug.h | 45 + .../sys_controller_bsp/HAL/inc/sys/alt_dev.h | 115 + .../sys_controller_bsp/HAL/inc/sys/alt_dma.h | 226 + .../HAL/inc/sys/alt_dma_dev.h | 200 + .../HAL/inc/sys/alt_driver.h | 168 + .../HAL/inc/sys/alt_errno.h | 87 + .../HAL/inc/sys/alt_exceptions.h | 166 + .../HAL/inc/sys/alt_flash.h | 179 + .../HAL/inc/sys/alt_flash_dev.h | 100 + .../HAL/inc/sys/alt_flash_types.h | 64 + .../sys_controller_bsp/HAL/inc/sys/alt_irq.h | 245 + .../HAL/inc/sys/alt_irq_entry.h | 39 + .../HAL/inc/sys/alt_license_reminder_ucosii.h | 77 + .../HAL/inc/sys/alt_llist.h | 123 + .../sys_controller_bsp/HAL/inc/sys/alt_load.h | 78 + .../HAL/inc/sys/alt_log_printf.h | 349 + .../HAL/inc/sys/alt_set_args.h | 71 + .../sys_controller_bsp/HAL/inc/sys/alt_sim.h | 91 + .../HAL/inc/sys/alt_stack.h | 126 + .../HAL/inc/sys/alt_stdio.h | 66 + .../HAL/inc/sys/alt_sys_init.h | 62 + .../HAL/inc/sys/alt_sys_wrappers.h | 100 + .../HAL/inc/sys/alt_timestamp.h | 60 + .../HAL/inc/sys/alt_warning.h | 75 + .../sys_controller_bsp/HAL/inc/sys/ioctl.h | 90 + .../sys_controller_bsp/HAL/inc/sys/termios.h | 181 + .../HAL/src/alt_alarm_start.c | 112 + .../HAL/src/alt_busy_sleep.c | 133 + .../sys_controller_bsp/HAL/src/alt_close.c | 103 + .../HAL/src/alt_dcache_flush.c | 70 + .../HAL/src/alt_dcache_flush_all.c | 51 + .../HAL/src/alt_dcache_flush_no_writeback.c | 69 + software/sys_controller_bsp/HAL/src/alt_dev.c | 149 + .../HAL/src/alt_dev_llist_insert.c | 59 + .../HAL/src/alt_dma_rxchan_open.c | 63 + .../HAL/src/alt_dma_txchan_open.c | 63 + .../sys_controller_bsp/HAL/src/alt_do_ctors.c | 64 + .../sys_controller_bsp/HAL/src/alt_do_dtors.c | 64 + .../HAL/src/alt_ecc_fatal_entry.S | 102 + .../HAL/src/alt_ecc_fatal_exception.c | 75 + .../sys_controller_bsp/HAL/src/alt_env_lock.c | 53 + .../sys_controller_bsp/HAL/src/alt_environ.c | 42 + .../sys_controller_bsp/HAL/src/alt_errno.c | 44 + .../HAL/src/alt_exception_entry.S | 376 + .../HAL/src/alt_exception_muldiv.S | 583 + .../HAL/src/alt_exception_trap.S | 95 + .../sys_controller_bsp/HAL/src/alt_execve.c | 55 + .../sys_controller_bsp/HAL/src/alt_exit.c | 71 + .../sys_controller_bsp/HAL/src/alt_fcntl.c | 101 + .../sys_controller_bsp/HAL/src/alt_fd_lock.c | 75 + .../HAL/src/alt_fd_unlock.c | 56 + .../sys_controller_bsp/HAL/src/alt_find_dev.c | 88 + .../HAL/src/alt_find_file.c | 89 + .../HAL/src/alt_flash_dev.c | 69 + .../sys_controller_bsp/HAL/src/alt_fork.c | 57 + .../sys_controller_bsp/HAL/src/alt_fs_reg.c | 75 + .../sys_controller_bsp/HAL/src/alt_fstat.c | 128 + .../sys_controller_bsp/HAL/src/alt_get_fd.c | 105 + .../sys_controller_bsp/HAL/src/alt_getchar.c | 70 + .../sys_controller_bsp/HAL/src/alt_getpid.c | 47 + .../sys_controller_bsp/HAL/src/alt_gettod.c | 125 + .../sys_controller_bsp/HAL/src/alt_gmon.c | 272 + .../HAL/src/alt_icache_flush.c | 84 + .../HAL/src/alt_icache_flush_all.c | 46 + software/sys_controller_bsp/HAL/src/alt_iic.c | 106 + .../HAL/src/alt_iic_isr_register.c | 104 + .../HAL/src/alt_instruction_exception_entry.c | 206 + .../src/alt_instruction_exception_register.c | 82 + .../HAL/src/alt_io_redirect.c | 98 + .../sys_controller_bsp/HAL/src/alt_ioctl.c | 170 + .../HAL/src/alt_irq_entry.S | 108 + .../HAL/src/alt_irq_handler.c | 169 + .../HAL/src/alt_irq_register.c | 102 + .../sys_controller_bsp/HAL/src/alt_irq_vars.c | 47 + .../sys_controller_bsp/HAL/src/alt_isatty.c | 125 + .../sys_controller_bsp/HAL/src/alt_kill.c | 121 + .../sys_controller_bsp/HAL/src/alt_link.c | 56 + .../sys_controller_bsp/HAL/src/alt_load.c | 88 + .../HAL/src/alt_log_macro.S | 60 + .../HAL/src/alt_log_printf.c | 479 + .../sys_controller_bsp/HAL/src/alt_lseek.c | 117 + .../sys_controller_bsp/HAL/src/alt_main.c | 161 + .../HAL/src/alt_malloc_lock.c | 52 + .../sys_controller_bsp/HAL/src/alt_mcount.S | 198 + .../sys_controller_bsp/HAL/src/alt_open.c | 173 + .../sys_controller_bsp/HAL/src/alt_printf.c | 132 + .../sys_controller_bsp/HAL/src/alt_putchar.c | 68 + .../sys_controller_bsp/HAL/src/alt_putstr.c | 64 + .../sys_controller_bsp/HAL/src/alt_read.c | 125 + .../HAL/src/alt_release_fd.c | 54 + .../HAL/src/alt_remap_cached.c | 55 + .../HAL/src/alt_remap_uncached.c | 54 + .../sys_controller_bsp/HAL/src/alt_rename.c | 55 + .../sys_controller_bsp/HAL/src/alt_sbrk.c | 136 + .../sys_controller_bsp/HAL/src/alt_settod.c | 96 + .../HAL/src/alt_software_exception.S | 53 + .../sys_controller_bsp/HAL/src/alt_stat.c | 59 + .../sys_controller_bsp/HAL/src/alt_tick.c | 149 + .../sys_controller_bsp/HAL/src/alt_times.c | 71 + .../HAL/src/alt_uncached_free.c | 53 + .../HAL/src/alt_uncached_malloc.c | 77 + .../sys_controller_bsp/HAL/src/alt_unlink.c | 55 + .../sys_controller_bsp/HAL/src/alt_usleep.c | 52 + .../sys_controller_bsp/HAL/src/alt_wait.c | 52 + .../sys_controller_bsp/HAL/src/alt_write.c | 138 + .../HAL/src/altera_nios2_gen2_irq.c | 37 + software/sys_controller_bsp/HAL/src/crt0.S | 521 + software/sys_controller_bsp/Makefile | 790 + software/sys_controller_bsp/alt_sys_init.c | 102 + software/sys_controller_bsp/create-this-bsp | 52 + .../Altera_UP_SD_Card_Avalon_Interface_mod.h | 166 + .../drivers/inc/altera_avalon_jtag_uart.h | 198 + .../drivers/inc/altera_avalon_jtag_uart_fd.h | 125 + .../inc/altera_avalon_jtag_uart_regs.h | 73 + .../drivers/inc/altera_avalon_pio_regs.h | 67 + .../drivers/inc/altera_epcq_controller_mod.h | 126 + .../inc/altera_epcq_controller_mod_regs.h | 260 + .../sys_controller_bsp/drivers/inc/ci_crc.h | 38 + software/sys_controller_bsp/drivers/inc/crc.h | 109 + .../drivers/inc/i2c_opencores.h | 33 + .../drivers/inc/i2c_opencores_regs.h | 77 + .../Altera_UP_SD_Card_Avalon_Interface_mod.c | 1908 ++ .../drivers/src/altera_avalon_jtag_uart_fd.c | 86 + .../src/altera_avalon_jtag_uart_init.c | 256 + .../src/altera_avalon_jtag_uart_ioctl.c | 86 + .../src/altera_avalon_jtag_uart_read.c | 205 + .../src/altera_avalon_jtag_uart_write.c | 217 + .../drivers/src/altera_epcq_controller_mod.c | 797 + .../sys_controller_bsp/drivers/src/ci_crc.c | 97 + software/sys_controller_bsp/drivers/src/crc.c | 265 + .../drivers/src/i2c_opencores.c | 206 + software/sys_controller_bsp/libhal_bsp.a | Bin 0 -> 107610 bytes software/sys_controller_bsp/linker.h | 103 + software/sys_controller_bsp/linker.x | 405 + software/sys_controller_bsp/mem_init.mk | 362 + software/sys_controller_bsp/memory.gdb | 53 + software/sys_controller_bsp/public.mk | 400 + software/sys_controller_bsp/settings.bsp | 985 + software/sys_controller_bsp/system.h | 484 + sys.qsys | 951 + sys.sopcinfo | 14864 ++++++++++++++++ tools/create_fw_img.c | 174 + 264 files changed, 66416 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 ip/altera_epcq_controller_mod/HAL/inc/altera_epcq_controller_mod.h create mode 100644 ip/altera_epcq_controller_mod/HAL/src/altera_epcq_controller_mod.c create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller.sv create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller_arb.sv create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller_fifo.v create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller_hw.tcl create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller_sw.tcl create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper.sv.terp create mode 100644 ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper_hw.tcl create mode 100644 ip/altera_epcq_controller_mod/inc/altera_epcq_controller_mod_regs.h create mode 100644 ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys.v create mode 100644 ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys_hw.tcl create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/doc/SD_Card_Interface_for_SoPC_Builder.pdf create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC16_Generator.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd create mode 100644 ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd create mode 100644 ip/i2c_opencores/Docs/I2C_tests.c create mode 100644 ip/i2c_opencores/Docs/i2c_specs.pdf create mode 100644 ip/i2c_opencores/HAL/inc/i2c_opencores.h create mode 100644 ip/i2c_opencores/HAL/src/component.mk create mode 100644 ip/i2c_opencores/HAL/src/i2c_opencores.c create mode 100644 ip/i2c_opencores/i2c_master_bit_ctrl.v create mode 100644 ip/i2c_opencores/i2c_master_byte_ctrl.v create mode 100644 ip/i2c_opencores/i2c_master_defines.v create mode 100644 ip/i2c_opencores/i2c_master_top.v create mode 100644 ip/i2c_opencores/i2c_opencores.v create mode 100644 ip/i2c_opencores/i2c_opencores_hw.tcl create mode 100644 ip/i2c_opencores/i2c_opencores_sw.tcl create mode 100644 ip/i2c_opencores/inc/i2c_opencores_regs.h create mode 100644 ip/i2c_opencores/timescale.v create mode 100644 ip/nios2_hw_crc/HAL/doc/crc_main.c create mode 100644 ip/nios2_hw_crc/HAL/inc/ci_crc.h create mode 100644 ip/nios2_hw_crc/HAL/inc/crc.h create mode 100644 ip/nios2_hw_crc/HAL/src/ci_crc.c create mode 100644 ip/nios2_hw_crc/HAL/src/crc.c create mode 100644 ip/nios2_hw_crc/hdl/CRC_Component.v create mode 100644 ip/nios2_hw_crc/hdl/CRC_Custom_Instruction.v create mode 100644 ip/nios2_hw_crc/nios2_hw_crc32_hw.tcl create mode 100644 ip/nios2_hw_crc/nios2_hw_crc32_sw.tcl create mode 100644 ossc.qpf create mode 100644 ossc.qsf create mode 100644 ossc.sdc create mode 100644 rtl/ir_rcv.v create mode 100644 rtl/linebuf.qip create mode 100644 rtl/linebuf.v create mode 100644 rtl/ossc.v create mode 100644 rtl/pll_2x.ppf create mode 100644 rtl/pll_2x.qip create mode 100644 rtl/pll_2x.v create mode 100644 rtl/pll_3x.ppf create mode 100644 rtl/pll_3x.qip create mode 100644 rtl/pll_3x.v create mode 100644 rtl/pll_3x_lowfreq.ppf create mode 100644 rtl/pll_3x_lowfreq.qip create mode 100644 rtl/pll_3x_lowfreq.v create mode 100644 rtl/scanconverter.v create mode 100644 rtl/timescale.v create mode 100644 rtl/videogen.v create mode 100644 software/sys_controller/Makefile create mode 100644 software/sys_controller/av_controller.c create mode 100644 software/sys_controller/it6613/EDID.c create mode 100644 software/sys_controller/it6613/HDMI_COMMON.h create mode 100644 software/sys_controller/it6613/HDMI_TX.c create mode 100644 software/sys_controller/it6613/HDMI_TX.h create mode 100644 software/sys_controller/it6613/edid.h create mode 100644 software/sys_controller/it6613/hdmitx.h create mode 100644 software/sys_controller/it6613/hdmitx_nios2.c create mode 100644 software/sys_controller/it6613/it6613.c create mode 100644 software/sys_controller/it6613/it6613.h create mode 100644 software/sys_controller/it6613/it6613_drv.c create mode 100644 software/sys_controller/it6613/it6613_drv.h create mode 100644 software/sys_controller/it6613/it6613_sys.c create mode 100644 software/sys_controller/it6613/it6613_sys.h create mode 100644 software/sys_controller/it6613/typedef.h create mode 100644 software/sys_controller/mem_init/epcq_controller_0.hex create mode 100644 software/sys_controller/mem_init/meminit.qip create mode 100644 software/sys_controller/mem_init/meminit.spd create mode 100644 software/sys_controller/mem_init/sys_onchip_memory2_0.hex create mode 100644 software/sys_controller/spi_charlcd/lcd.c create mode 100644 software/sys_controller/spi_charlcd/lcd.h create mode 100644 software/sys_controller/sysconfig.h create mode 100644 software/sys_controller/ths7353/ths7353.c create mode 100644 software/sys_controller/ths7353/ths7353.h create mode 100644 software/sys_controller/tvp7002/tvp7002.c create mode 100644 software/sys_controller/tvp7002/tvp7002.h create mode 100644 software/sys_controller/tvp7002/tvp7002_regs.h create mode 100644 software/sys_controller/tvp7002/video_modes.c create mode 100644 software/sys_controller/tvp7002/video_modes.h create mode 100644 software/sys_controller_bsp/HAL/inc/alt_types.h create mode 100644 software/sys_controller_bsp/HAL/inc/altera_nios2_gen2_irq.h create mode 100644 software/sys_controller_bsp/HAL/inc/io.h create mode 100644 software/sys_controller_bsp/HAL/inc/nios2.h create mode 100644 software/sys_controller_bsp/HAL/inc/os/alt_flag.h create mode 100644 software/sys_controller_bsp/HAL/inc/os/alt_hooks.h create mode 100644 software/sys_controller_bsp/HAL/inc/os/alt_sem.h create mode 100644 software/sys_controller_bsp/HAL/inc/os/alt_syscall.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_alarm.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_busy_sleep.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_dev_llist.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_exception_handler_registry.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_file.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_iic_isr_register.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_irq_table.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_legacy_irq.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/alt_no_error.h create mode 100644 software/sys_controller_bsp/HAL/inc/priv/nios2_gmon_data.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_alarm.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_cache.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_debug.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_dev.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_dma.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_dma_dev.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_driver.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_errno.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_exceptions.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_flash.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_flash_dev.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_flash_types.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_irq.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_irq_entry.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_license_reminder_ucosii.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_llist.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_load.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_log_printf.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_set_args.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_sim.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_stack.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_stdio.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_sys_init.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_sys_wrappers.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_timestamp.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/alt_warning.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/ioctl.h create mode 100644 software/sys_controller_bsp/HAL/inc/sys/termios.h create mode 100644 software/sys_controller_bsp/HAL/src/alt_alarm_start.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_busy_sleep.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_close.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dcache_flush.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dcache_flush_all.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dcache_flush_no_writeback.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dev.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dev_llist_insert.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dma_rxchan_open.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_dma_txchan_open.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_do_ctors.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_do_dtors.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_ecc_fatal_entry.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_ecc_fatal_exception.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_env_lock.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_environ.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_errno.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_exception_entry.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_exception_muldiv.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_exception_trap.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_execve.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_exit.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_fcntl.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_fd_lock.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_fd_unlock.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_find_dev.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_find_file.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_flash_dev.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_fork.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_fs_reg.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_fstat.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_get_fd.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_getchar.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_getpid.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_gettod.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_gmon.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_icache_flush.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_icache_flush_all.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_iic.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_iic_isr_register.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_instruction_exception_entry.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_instruction_exception_register.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_io_redirect.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_ioctl.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_irq_entry.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_irq_handler.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_irq_register.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_irq_vars.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_isatty.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_kill.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_link.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_load.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_log_macro.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_log_printf.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_lseek.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_main.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_malloc_lock.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_mcount.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_open.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_printf.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_putchar.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_putstr.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_read.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_release_fd.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_remap_cached.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_remap_uncached.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_rename.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_sbrk.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_settod.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_software_exception.S create mode 100644 software/sys_controller_bsp/HAL/src/alt_stat.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_tick.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_times.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_uncached_free.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_uncached_malloc.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_unlink.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_usleep.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_wait.c create mode 100644 software/sys_controller_bsp/HAL/src/alt_write.c create mode 100644 software/sys_controller_bsp/HAL/src/altera_nios2_gen2_irq.c create mode 100644 software/sys_controller_bsp/HAL/src/crt0.S create mode 100644 software/sys_controller_bsp/Makefile create mode 100644 software/sys_controller_bsp/alt_sys_init.c create mode 100755 software/sys_controller_bsp/create-this-bsp create mode 100644 software/sys_controller_bsp/drivers/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h create mode 100644 software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart.h create mode 100644 software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_fd.h create mode 100644 software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_regs.h create mode 100644 software/sys_controller_bsp/drivers/inc/altera_avalon_pio_regs.h create mode 100644 software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod.h create mode 100644 software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod_regs.h create mode 100644 software/sys_controller_bsp/drivers/inc/ci_crc.h create mode 100644 software/sys_controller_bsp/drivers/inc/crc.h create mode 100644 software/sys_controller_bsp/drivers/inc/i2c_opencores.h create mode 100644 software/sys_controller_bsp/drivers/inc/i2c_opencores_regs.h create mode 100644 software/sys_controller_bsp/drivers/src/Altera_UP_SD_Card_Avalon_Interface_mod.c create mode 100644 software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_fd.c create mode 100644 software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_init.c create mode 100644 software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_ioctl.c create mode 100644 software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_read.c create mode 100644 software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_write.c create mode 100644 software/sys_controller_bsp/drivers/src/altera_epcq_controller_mod.c create mode 100644 software/sys_controller_bsp/drivers/src/ci_crc.c create mode 100644 software/sys_controller_bsp/drivers/src/crc.c create mode 100644 software/sys_controller_bsp/drivers/src/i2c_opencores.c create mode 100644 software/sys_controller_bsp/libhal_bsp.a create mode 100644 software/sys_controller_bsp/linker.h create mode 100644 software/sys_controller_bsp/linker.x create mode 100644 software/sys_controller_bsp/mem_init.mk create mode 100644 software/sys_controller_bsp/memory.gdb create mode 100644 software/sys_controller_bsp/public.mk create mode 100644 software/sys_controller_bsp/settings.bsp create mode 100644 software/sys_controller_bsp/system.h create mode 100644 sys.qsys create mode 100644 sys.sopcinfo create mode 100644 tools/create_fw_img.c diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d7617a3 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +Open Source Scan Converter +============== + +Documentation coming soon... diff --git a/ip/altera_epcq_controller_mod/HAL/inc/altera_epcq_controller_mod.h b/ip/altera_epcq_controller_mod/HAL/inc/altera_epcq_controller_mod.h new file mode 100644 index 0000000..2c58d09 --- /dev/null +++ b/ip/altera_epcq_controller_mod/HAL/inc/altera_epcq_controller_mod.h @@ -0,0 +1,126 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALT_EPCQ_CONTROLLER_H__ +#define __ALT_EPCQ_CONTROLLER_H__ + +#include "alt_types.h" +#include "sys/alt_flash_dev.h" +#include "sys/alt_llist.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** + * Description of the EPCQ controller + */ +typedef struct alt_epcq_controller_dev +{ + alt_flash_dev dev; + + alt_u32 data_base; /** base address of data slave */ + alt_u32 data_end; /** end address of data slave (not inclusive) */ + alt_u32 csr_base; /** base address of CSR slave */ + alt_u32 size_in_bytes; /** size of memory in bytes */ + alt_u32 is_epcs; /** 1 if device is an EPCS device */ + alt_u32 number_of_sectors; /** number of flash sectors */ + alt_u32 sector_size; /** size of each flash sector */ + alt_u32 page_size; /** page size */ + alt_u32 silicon_id; /** ID of silicon used with EPCQ IP */ +} alt_epcq_controller_dev; + +/** +* Macros used by alt_sys_init.c to create data storage for driver instance +*/ +#define ALTERA_EPCQ_CONTROLLER_MOD_AVL_MEM_AVL_CSR_INSTANCE(epcq_name, avl_mem, avl_csr, epcq_dev) \ +alt_epcq_controller_dev epcq_dev = \ +{ \ + .dev = { \ + .llist = ALT_LLIST_ENTRY, \ + .name = avl_mem##_NAME, \ + .write = alt_epcq_controller_write, \ + .read = alt_epcq_controller_read, \ + .get_info = alt_epcq_controller_get_info, \ + .erase_block = alt_epcq_controller_erase_block, \ + .write_block = alt_epcq_controller_write_block, \ + .base_addr = ((void*)(avl_mem##_BASE)), \ + .length = ((int)(avl_mem##_SPAN)), \ + .lock = alt_epcq_controller_lock , \ + }, \ + .data_base = ((alt_u32)(avl_mem##_BASE)), \ + .data_end = ((alt_u32)(avl_mem##_BASE) + (alt_u32)(avl_mem##_SPAN)), \ + .csr_base = ((alt_u32)(avl_csr##_BASE)), \ + .size_in_bytes = ((alt_u32)(avl_mem##_SPAN)), \ + .is_epcs = ((alt_u32)(avl_mem##_IS_EPCS)), \ + .number_of_sectors = ((alt_u32)(avl_mem##_NUMBER_OF_SECTORS)), \ + .sector_size = ((alt_u32)(avl_mem##_SECTOR_SIZE)), \ + .page_size = ((alt_u32)(avl_mem##_PAGE_SIZE)) , \ +} + +/* + Public API + + Refer to Using Flash Devices in the + Developing Programs Using the Hardware Abstraction Layer chapter + of the Nios II Software Developer's Handbook. + +*/ +int alt_epcq_controller_read(alt_flash_dev *flash_info, int offset, void *dest_addr, int length); + +int alt_epcq_controller_get_info(alt_flash_fd *fd, flash_region **info, int *number_of_regions); + +int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset); + +int alt_epcq_controller_write_block(alt_flash_dev *flash_info, int block_offset, int data_offset, const void *data, int length); + +int alt_epcq_controller_write(alt_flash_dev *flash_info, int offset, const void *src_addr, int length); + +int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock); + + +/* + * Initialization function + */ +extern alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *dev); + +/* + * alt_sys_init.c will call this macro automatically initialize the driver instance + */ +#define ALTERA_EPCQ_CONTROLLER_MOD_INIT(name, dev) \ + altera_epcq_controller_init(&dev); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_EPCQ_CONTROLLER_H__ */ diff --git a/ip/altera_epcq_controller_mod/HAL/src/altera_epcq_controller_mod.c b/ip/altera_epcq_controller_mod/HAL/src/altera_epcq_controller_mod.c new file mode 100644 index 0000000..5147a95 --- /dev/null +++ b/ip/altera_epcq_controller_mod/HAL/src/altera_epcq_controller_mod.c @@ -0,0 +1,797 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include +#include "sys/param.h" +#include "alt_types.h" +#include "altera_epcq_controller_mod_regs.h" +#include "altera_epcq_controller_mod.h" +#include "priv/alt_busy_sleep.h" +#include "sys/alt_debug.h" +#include "sys/alt_cache.h" + + +ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments(alt_epcq_controller_dev *flash_info,alt_u32 offset, alt_u32 length); +alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info); + +/* + * Public API + * + * Refer to “Using Flash Devices” in the + * Developing Programs Using the Hardware Abstraction Layer chapter + * of the Nios II Software Developer’s Handbook. + */ + + + /** + * alt_epcq_controller_lock + * + * Locks the range of the memory sectors, which + * protected from write and erase. + * + * Arguments: + * - *flash_info: Pointer to general flash device structure. + * - sectors_to_lock: Block protection bits in EPCQ ==> Bit4 | Bit3 | Bit2 | Bit1 | Bit0 + * TB | BP3 | BP2 | BP1 | BP0 + * For details of setting sectors protection, please refer to EPCQ datasheet. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -ETIME -> Time out and skipping the looping after 0.7 sec. + * -ENOLCK -> Sectors lock failed. +**/ +int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock) +{ + alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */ + alt_epcq_controller_dev* epcq_flash_info = NULL; + alt_u32 result = 0; + alt_32 status = 0; + + /* return -EINVAL if flash_info is NULL */ + if(NULL == flash_info || 0 > sectors_to_lock) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* sector value should occupy bits 17:8 */ + mem_op_value = sectors_to_lock << 8; + + /* sector protect commands 0b11 occupies lower 2 bits */ + mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD; + + /* write sector protect command to EPCQ_MEM_OP register to protect sectors */ + IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value); + + /* poll write in progress to make sure no operation is in progress */ + status = alt_epcq_poll_for_write_in_progress(epcq_flash_info); + if(status != 0) + { + return status; + } + + status = IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base); + result |= (status >> 2) & 0x07; /* extract out BP3 - BP0 */ + result |= (status >> 3) & 0x08; /* extract out BP4 */ + result |= (status >> 1) & 0x10; /* extract out TOP/BOTTOM bit */ + + if(result != sectors_to_lock) + { + return -ENOLCK; + } + + return 0; +} + +/** + * alt_epcq_controller_get_info + * + * Pass the table of erase blocks to the user. This flash will return a single + * flash_region that gives the number and size of sectors for the device used. + * + * Arguments: + * - *fd: Pointer to general flash device structure. + * - **info: Pointer to flash region + * - *number_of_regions: Pointer to number of regions + * + * For details of setting sectors protection, please refer to EPCQ datasheet. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> Could be hardware problem. +**/ +int alt_epcq_controller_get_info +( + alt_flash_fd *fd, /** flash device descriptor */ + flash_region **info, /** pointer to flash_region will be stored here */ + int *number_of_regions /** number of regions will be stored here */ +) +{ + alt_flash_dev* flash = NULL; + + /* return -EINVAL if fd,info and number_of_regions are NULL */ + if(NULL == fd || NULL == info || NULL == number_of_regions) + { + return -EINVAL; + } + + flash = (alt_flash_dev*)fd; + + *number_of_regions = flash->number_of_regions; + + if (!flash->number_of_regions) + { + return -EIO; + } + else + { + *info = &flash->region_info[0]; + } + + return 0; +} + +/** + * alt_epcq_controller_erase_block + * + * This function erases a single flash sector. + * + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - block_offset: byte-addressed offset, from start of flash, of the sector to be erased + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> write failed, sector might be protected +**/ +int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset) +{ + alt_32 ret_code = 0; + alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */ + alt_epcq_controller_dev* epcq_flash_info = NULL; + alt_u32 sector_number = 0; + + /* return -EINVAL if flash_info is NULL */ + if(NULL == flash_info) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* + * Sanity checks that block_offset is within the flash memory span and that the + * block offset is sector aligned. + * + */ + if((block_offset < 0) + || (block_offset >= epcq_flash_info->size_in_bytes) + || (block_offset & (epcq_flash_info->sector_size - 1)) != 0) + { + return -EINVAL; + } + + /* calculate current sector/block number */ + sector_number = (block_offset/(epcq_flash_info->sector_size)); + + /* sector value should occupy bits 23:8 */ + mem_op_value = (sector_number << 8) & ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK; + + /* sector erase commands 0b10 occupies lower 2 bits */ + mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD; + + /* write sector erase command to EPCQ_MEM_OP register to erase sector "sector_number" */ + IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value); + + /* check whether erase triggered a illegal erase interrupt */ + if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) & + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK) == + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE) + { + /* clear register */ + /* EPCQ_ISR access is write one to clear (W1C) */ + IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base, + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK ); + return -EIO; /* erase failed, sector might be protected */ + } + + return ret_code; +} + +/** + * alt_epcq_controller_write_block + * + * This function writes one block/sector of data to flash. The length of the write can NOT + * spill into the adjacent sector. + * + * It assumes that someone has already erased the appropriate sector(s). + * + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - block_offset: byte-addressed offset, from the start of flash, of the sector to written to + * - data-offset: Byte offset (unaligned access) of write into flash memory. + * For best performance, word(32 bits - aligned access) offset of write is recommended. + * - *src_addr: source buffer + * - length: size of writing + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> write failed, sector might be protected +**/ +int alt_epcq_controller_write_block +( + alt_flash_dev *flash_info, /** flash device info */ + int block_offset, /** sector/block offset in byte addressing */ + int data_offset, /** offset of write from base address */ + const void *data, /** data to be written */ + int length /** bytes of data to be written, >0 */ +) +{ + alt_u32 buffer_offset = 0; /** offset into data buffer to get write data */ + alt_u32 remaining_length = length; /** length left to write */ + alt_u32 write_offset = data_offset; /** offset into flash to write too */ + + alt_epcq_controller_dev *epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* + * Sanity checks that data offset is not larger then a sector, that block offset is + * sector aligned and within the valid flash memory range and a write doesn't spill into + * the adjacent flash sector. + */ + if(block_offset < 0 + || data_offset < 0 + || NULL == flash_info + || NULL == data + || data_offset >= epcq_flash_info->size_in_bytes + || block_offset >= epcq_flash_info->size_in_bytes + || length > (epcq_flash_info->sector_size - (data_offset - block_offset)) + || length < 0 + || (block_offset & (epcq_flash_info->sector_size - 1)) != 0) + { + return -EINVAL; + } + + /* + * Do writes one 32-bit word at a time. + * We need to make sure that we pad the first few bytes so they're word aligned if they are + * not already. + */ + while (remaining_length > 0) + { + alt_u32 word_to_write = 0xFFFFFFFF; /** initialize word to write to blank word */ + alt_u32 padding = 0; /** bytes to pad the next word that is written */ + alt_u32 bytes_to_copy = sizeof(alt_u32); /** number of bytes from source to copy */ + + /* + * we need to make sure the write is word aligned + * this should only be true at most 1 time + */ + if (0 != (write_offset & (sizeof(alt_u32) - 1))) + { + /* + * data is not word aligned + * calculate padding bytes need to add before start of a data offset + */ + padding = write_offset & (sizeof(alt_u32) - 1); + + /* update variables to account for padding being added */ + bytes_to_copy -= padding; + + if(bytes_to_copy > remaining_length) + { + bytes_to_copy = remaining_length; + } + + write_offset = write_offset - padding; + if(0 != (write_offset & (sizeof(alt_u32) - 1))) + { + return -EINVAL; + } + } + else + { + if(bytes_to_copy > remaining_length) + { + bytes_to_copy = remaining_length; + } + } + + /* prepare the word to be written */ + memcpy((((void*)&word_to_write)) + padding, ((void*)data) + buffer_offset, bytes_to_copy); + + /* update offset and length variables */ + buffer_offset += bytes_to_copy; + remaining_length -= bytes_to_copy; + + /* write to flash 32 bits at a time */ + IOWR_32DIRECT(epcq_flash_info->data_base, write_offset, word_to_write); + + /* check whether write triggered a illegal write interrupt */ + if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) & + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK) == + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE) + { + /* clear register */ + IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base, + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK ); + return -EIO; /** write failed, sector might be protected */ + } + + /* update current offset */ + write_offset = write_offset + sizeof(alt_u32); + } + + return 0; +} + +/** + * alt_epcq_controller_write + * + * Program the data into the flash at the selected address. + * + * The different between this function and alt_epcq_controller_write_block function + * is that this function (alt_epcq_controller_write) will automatically erase a block as needed + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - offset: Byte offset (unaligned access) of write to flash memory. For best performance, + * word(32 bits - aligned access) offset of write is recommended. + * - *src_addr: source buffer + * - length: size of writing + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> write failed, sector might be protected + * +**/ +int alt_epcq_controller_write( + alt_flash_dev *flash_info, /** device info */ + int offset, /** offset of write from base address */ + const void *src_addr, /** source buffer */ + int length /** size of writing */ +) +{ + alt_32 ret_code = 0; + + alt_epcq_controller_dev *epcq_flash_info = NULL; + + alt_u32 write_offset = offset; /** address of next byte to write */ + alt_u32 remaining_length = length; /** length of write data left to be written */ + alt_u32 buffer_offset = 0; /** offset into source buffer to get write data */ + alt_u32 i = 0; + + /* return -EINVAL if flash_info and src_addr are NULL */ + if(NULL == flash_info || NULL == src_addr) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* make sure the write parameters are within the bounds of the flash */ + ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length); + + if(0 != ret_code) + { + return ret_code; + } + + /* + * This loop erases and writes data one sector at a time. We check for write completion + * before starting the next sector. + */ + for(i = offset/epcq_flash_info->sector_size ; i < epcq_flash_info->number_of_sectors; i++) + { + alt_u32 block_offset = 0; /** block offset in byte addressing */ + alt_u32 offset_within_current_sector = 0; /** offset into current sector to write */ + alt_u32 length_to_write = 0; /** length to write to current sector */ + + if(0 >= remaining_length) + { + break; /* out of data to write */ + } + + /* calculate current sector/block offset in byte addressing */ + block_offset = write_offset & ~(epcq_flash_info->sector_size - 1); + + /* calculate offset into sector/block if there is one */ + if(block_offset != write_offset) + { + offset_within_current_sector = write_offset - block_offset; + } + + /* erase sector */ + ret_code = alt_epcq_controller_erase_block(flash_info, block_offset); + + if(0 != ret_code) + { + return ret_code; + } + + /* calculate the byte size of data to be written in a sector */ + length_to_write = MIN(epcq_flash_info->sector_size - offset_within_current_sector, + remaining_length); + + /* write data to erased block */ + ret_code = alt_epcq_controller_write_block(flash_info, block_offset, write_offset, + src_addr + buffer_offset, length_to_write); + + + if(0 != ret_code) + { + return ret_code; + } + + /* update remaining length and buffer_offset pointer */ + remaining_length -= length_to_write; + buffer_offset += length_to_write; + write_offset += length_to_write; + } + + return ret_code; +} + +/** + * alt_epcq_controller_read + * + * There's no real need to use this function as opposed to using memcpy directly. It does + * do some sanity checks on the bounds of the read. + * + * Arguments: + * - *flash_info: Pointer to general flash device structure. + * - offset: offset read from flash memory. + * - *dest_addr: destination buffer + * - length: size of reading + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments +**/ +int alt_epcq_controller_read +( + alt_flash_dev *flash_info, /** device info */ + int offset, /** offset of read from base address */ + void *dest_addr, /** destination buffer */ + int length /** size of read */ +) +{ + alt_32 ret_code = 0; + alt_epcq_controller_dev *epcq_flash_info = NULL; + + /* return -EINVAL if flash_info and dest_addr are NULL */ + if(NULL == flash_info || NULL == dest_addr) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* validate arguments */ + ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length); + + /* copy data from flash to destination address */ + if(0 == ret_code) + { + memcpy(dest_addr, (alt_u8*)epcq_flash_info->data_base + offset, length); + } + + return ret_code; +} + +/** + * altera_epcq_controller_init + * + * alt_sys_init.c will call this function automatically through macro + * + * Information in system.h is checked against expected values that are determined by the silicon_id. + * If the information doesn't match then this system is configured incorrectly. Most likely the wrong + * type of EPCS or EPCQ device was selected when instantiating the soft IP. + * + * Arguments: + * - *flash: Pointer to EPCQ flash device structure. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments. + * -ENODEV -> System is configured incorrectly. +**/ +alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *flash) +{ + alt_u32 silicon_id = 0; + alt_u32 size_in_bytes = 0; + alt_u32 number_of_sectors = 0; + + /* return -EINVAL if flash is NULL */ + if(NULL == flash) + { + return -EINVAL; + } + + /* return -ENODEV if CSR slave is not attached */ + if(NULL == (void *)flash->csr_base) + { + return -ENODEV; + } + + + /* + * If flash is an EPCQ device, we read the EPCQ_RD_RDID register for the ID + * If flash is an EPCS device, we read the EPCQ_RD_SID register for the ID + * + * Whether or not the flash is a EPCQ or EPCS is indicated in the system.h. The system.h gets + * this value from the hw.tcl of the IP. If this value is set incorrectly, then things will go + * badly. + * + * In both cases, we can determine the number of sectors, which we can use + * to calculate a size. We compare that size to the system.h value to make sure + * the EPCQ soft IP was configured correctly. + */ + if(0 == flash->is_epcs) + { + /* If we're an EPCQ, we read EPCQ_RD_RDID for the silicon ID */ + silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_RDID(flash->csr_base); + silicon_id &= ALTERA_EPCQ_CONTROLLER_RDID_MASK; + + /* Determine which EPCQ device so we can figure out the number of sectors */ + /* EPCQ share the same ID for the same capacity*/ + switch(silicon_id) + { + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16: + { + number_of_sectors = 32; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32: + { + number_of_sectors = 64; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64: + { + number_of_sectors = 128; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128: + { + number_of_sectors = 256; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256: + { + number_of_sectors = 512; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512: + { + number_of_sectors = 1024; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024: + { + number_of_sectors = 2048; + break; + } + default: + { + return -ENODEV; + } + } + } + else { + /* If we're an EPCS, we read EPCQ_RD_SID for the silicon ID */ + silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_SID(flash->csr_base); + silicon_id &= ALTERA_EPCQ_CONTROLLER_SID_MASK; + + /* Determine which EPCS device so we can figure out various properties */ + switch(silicon_id) + { + case ALTERA_EPCQ_CONTROLLER_SID_EPCS16: + { + number_of_sectors = 32; + break; + } + case ALTERA_EPCQ_CONTROLLER_SID_EPCS64: + { + number_of_sectors = 128; + break; + } + case ALTERA_EPCQ_CONTROLLER_SID_EPCS128: + { + number_of_sectors = 256; + break; + } + default: + { + return -ENODEV; + } + } + } + + /* Calculate size of flash based on number of sectors */ + size_in_bytes = number_of_sectors * flash->sector_size; + + /* + * Make sure calculated size is the same size given in system.h + * Also check number of sectors is the same number given in system.h + * Otherwise the EPCQ IP was not configured correctly + */ + if( size_in_bytes != flash->size_in_bytes || + number_of_sectors != flash->number_of_sectors) + { + flash->dev.number_of_regions = 0; + return -ENODEV; + } + else + { + flash->silicon_id = silicon_id; + flash->number_of_sectors = number_of_sectors; + + /* + * populate fields of region_info required to conform to HAL API + * create 1 region that composed of "number_of_sectors" blocks + */ + flash->dev.number_of_regions = 1; + flash->dev.region_info[0].offset = 0; + flash->dev.region_info[0].region_size = size_in_bytes; + flash->dev.region_info[0].number_of_blocks = number_of_sectors; + flash->dev.region_info[0].block_size = flash->sector_size; + } + + + /* + * Register this device as a valid flash device type + * + * Only register the device if it's configured correctly. + */ + alt_flash_device_register(&(flash->dev)); + + + return 0; +} + + +/* + * Private API + * + * Helper functions used by Public API functions. + * + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - offset: Offset of read/write from base address. + * - length: Length of read/write in bytes. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + */ +/** + * Used to check that arguments to a read or write are valid + */ +ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments +( + alt_epcq_controller_dev *flash_info, /** device info */ + alt_u32 offset, /** offset of read/write */ + alt_u32 length /** length of read/write */ +) +{ + alt_epcq_controller_dev *epcq_flash_info = NULL; + alt_u32 start_address = 0; + alt_32 end_address = 0; + + /* return -EINVAL if flash_info is NULL */ + if(NULL == flash_info) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + start_address = epcq_flash_info->data_base + offset; /** first address of read or write */ + end_address = start_address + length; /** last address of read or write (not inclusive) */ + + /* make sure start and end address is less then the end address of the flash */ + if( + start_address >= epcq_flash_info->data_end || + end_address >= epcq_flash_info->data_end || + offset < 0 || + length < 0 + ) + { + return -EINVAL; + } + + return 0; +} + +/* + * Private function that polls write in progress bit EPCQ_RD_STATUS. + * + * Write in progress will be set if any of the following operations are in progress: + * -WRITE STATUS REGISTER + * -WRITE NONVOLATILE CONFIGURATION REGISTER + * -PROGRAM + * -ERASE + * + * Assumes EPCQ was configured correctly. + * + * If ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE is set, the function will time out after + * a period of time determined by that value. + * + * Arguments: + * - *epcq_flash_info: Pointer to EPCQ flash device structure. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -ETIME -> Time out and skipping the looping after 0.7 sec. + */ +alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info) +{ + /* we'll want to implement timeout if a timeout value is specified */ +#if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0 + alt_u32 timeout = ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE; + alt_u16 counter = 0; +#endif + + /* return -EINVAL if epcq_flash_info is NULL */ + if(NULL == epcq_flash_info) + { + return -EINVAL; + } + + /* while Write in Progress bit is set, we wait */ + while((IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base) & + ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK) == + ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY) + { + alt_busy_sleep(1); /* delay 1us */ +#if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0 + if(timeout <= counter ) + { + return -ETIME; + } + + counter++; +#endif + + } + + return 0; +} + + diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller.sv b/ip/altera_epcq_controller_mod/altera_epcq_controller.sv new file mode 100644 index 0000000..1263bdf --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller.sv @@ -0,0 +1,611 @@ +// (C) 2001-2015 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +// (C) 2001-2015 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + + + +`timescale 1ps / 1ps + +module altera_epcq_controller #( + parameter CS_WIDTH = 1, + parameter ENABLE_4BYTE_ADDR = 1, + parameter ADDR_WIDTH = 22, + parameter ASI_WIDTH = 1, + parameter DEVICE_FAMILY = "CYCLONE V", + parameter ASMI_ADDR_WIDTH = 22, + parameter CHIP_SELS = 1 +)( + input wire clk, + input wire reset_n, + + // ports to access csr + input wire avl_csr_write, + input wire avl_csr_read, + input wire [2:0] avl_csr_addr, + input wire [31:0] avl_csr_wrdata, + output reg [31:0] avl_csr_rddata, + output reg avl_csr_rddata_valid, + output reg avl_csr_waitrequest, + + // ports to access memory + input wire avl_mem_write, + input wire avl_mem_read, + input wire [ADDR_WIDTH-1:0] avl_mem_addr, + input wire [31:0] avl_mem_wrdata, + input wire [3:0] avl_mem_byteenable, + input wire [6:0] avl_mem_burstcount, + output wire [31:0] avl_mem_rddata, + output reg avl_mem_rddata_valid, + output reg avl_mem_waitrequest, + + // interrupt signal + output reg irq, + + // Disable dedicated active serial interface + input wire [ASI_WIDTH-1:0] epcq_dataout, + output reg epcq_dclk, + output reg [CS_WIDTH-1:0] epcq_scein, + output reg [ASI_WIDTH-1:0] epcq_sdoin, + output reg [ASI_WIDTH-1:0] epcq_dataoe, + + // ASMI PARALLEL interface + input wire [ASI_WIDTH-1:0] ddasi_dataoe, + output reg [ASI_WIDTH-1:0] ddasi_dataout, + input wire ddasi_dclk, + input wire [CS_WIDTH-1:0] ddasi_scein, + input reg [ASI_WIDTH-1:0] ddasi_sdoin, + + input wire asmi_busy, + input wire asmi_data_valid, + input wire [7:0] asmi_dataout, + output reg asmi_clkin, + output reg asmi_reset, + output reg [CS_WIDTH-1:0] asmi_sce, + output reg [ASMI_ADDR_WIDTH-1:0] asmi_addr, + output reg [7:0] asmi_datain, + output reg asmi_fast_read, + output wire asmi_rden, + output reg asmi_shift_bytes, + output reg asmi_en4b_addr, + output wire asmi_wren, + output reg asmi_write, + + input wire asmi_illegal_erase, + input wire asmi_illegal_write, + input wire [7:0] asmi_rdid_out, + input wire [7:0] asmi_status_out, + input wire [7:0] asmi_epcs_id, + output reg asmi_read_rdid, + output reg asmi_read_status, + output reg asmi_read_sid, + output reg asmi_bulk_erase, + output reg asmi_sector_erase, + output reg asmi_sector_protect +); + localparam LOCAL_ADDR_WIDTH = ADDR_WIDTH+2; + localparam CSR_DATA_WIDTH = 32; + localparam LAST_ADDR_BIT = (ASMI_ADDR_WIDTH == 24) ? 15 : + (ASMI_ADDR_WIDTH == 32) ? 23 : 15; + + reg [8:0] wr_burstcount_cnt, rd_burstcount_cnt; + reg [8:0] rd_mem_burstcount, wr_mem_burstcount; + + wire last_wr_byte; + wire access_csr_status, access_csr_sid, access_csr_rdid, access_csr_mem_op, access_isr, access_imr, access_sce; + wire read_status_combi, read_sid_combi, read_rdid_combi, read_isr_combi, read_imr_combi, write_isr_combi, write_imr_combi, write_sce_combi; + wire bulk_erase_combi, sector_erase_combi, sector_protect_combi; + wire wren_combi, illegal_write_combi, illegal_erase_combi; + wire m_illegal_write_combi, m_illegal_erase_combi; + wire read_mem_combi, write_mem_combi; + wire data_valid_combi, pending_wr_data; + wire detect_addroffset; + wire [8:0] wfifo_data_in_0, wfifo_data_in_1, wfifo_data_in_2, wfifo_data_in_3; + wire [ADDR_WIDTH-1:0] temp_mem_addr; + + reg reset_n_reg; + reg wr_mem_waitrequest, local_waitrequest; + reg illegal_write_reg, illegal_erase_reg, m_illegal_write_reg, m_illegal_erase_reg; + reg read_status_valid, read_sid_valid, read_rdid_valid, read_isr_valid, read_imr_valid; + reg read_status_en, read_sid_en, read_rdid_en; + reg wren_internal; + reg [LOCAL_ADDR_WIDTH-1:0] wr_mem_addr; + reg [7:0] rd_data_reg [4]; + reg [3:0][8:0] wr_data_reg; + reg [1:0] rd_cnt; + reg [1:0] wr_cnt; + reg [3:0] wr_data_reg_full; + reg detect_addroffset_reg, asmi_busy_reg; + reg [2:0] temp_sce; + + // Direct connection + assign asmi_clkin = clk; + assign asmi_reset = ~reset_n; + assign ddasi_dataout = epcq_dataout; + assign epcq_dclk = ddasi_dclk; + assign epcq_scein = ddasi_scein; + assign epcq_sdoin = ddasi_sdoin; + assign epcq_dataoe = ddasi_dataoe; + + // chip select + generate if (DEVICE_FAMILY == "Arria 10") begin + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + asmi_sce <= {CS_WIDTH{1'b0}}; + end +// to pack the address space this is needed + else if (write_mem_combi || read_mem_combi) begin + if (CHIP_SELS == 1 ) + asmi_sce <= 3'b001; + else if (CHIP_SELS == 2 && avl_mem_addr[ADDR_WIDTH-1] == 0) + asmi_sce <= 3'b001; + else if (CHIP_SELS == 2 && avl_mem_addr[ADDR_WIDTH-1] == 1) + asmi_sce <= 3'b010; + else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1] == 1) + asmi_sce <= 3'b100; + else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1:ADDR_WIDTH-2] == 0) + asmi_sce <= 3'b001; + else if (CHIP_SELS == 3 && avl_mem_addr[ADDR_WIDTH-1:ADDR_WIDTH-2] == 1) + asmi_sce <= 3'b010; + else + asmi_sce <= {CS_WIDTH{1'b0}}; + end + else if (write_sce_combi) begin + asmi_sce <= avl_csr_wrdata[2:0]; + end + else if (asmi_en4b_addr) begin + asmi_sce <= temp_sce; + end + end +// decoder ring if the CHIP_SEL is only 1 then avalon address is the temp address +// if the chipsele is 2 then need to remove top address bit +// if the chipelect is 3 then remove the top 2 address bits. + assign temp_mem_addr = CHIP_SELS == 1 ? avl_mem_addr:( CHIP_SELS == 2 ? {1'b0,avl_mem_addr[ADDR_WIDTH-2:0]}:{2'b00,avl_mem_addr[ADDR_WIDTH-3:0]}); + end + else begin + always @(posedge clk) begin + asmi_sce <= {CS_WIDTH{1'b0}}; + end + assign temp_mem_addr = avl_mem_addr; + end + endgenerate + + // wait_request generation logic + assign avl_mem_waitrequest = (asmi_busy || asmi_busy_reg) ? 1'b1 : (local_waitrequest || wr_mem_waitrequest); + assign avl_csr_waitrequest = (asmi_busy || asmi_busy_reg) ? 1'b1 : (local_waitrequest || wr_mem_waitrequest); + + // access CSR decoding logic + assign access_csr_status = (avl_csr_addr == 3'b000); + assign access_csr_sid = (avl_csr_addr == 3'b001); + assign access_csr_rdid = (avl_csr_addr == 3'b010); + assign access_csr_mem_op = (avl_csr_addr == 3'b011); + assign access_isr = (avl_csr_addr == 3'b100); + assign access_imr = (avl_csr_addr == 3'b101); + assign access_sce = (avl_csr_addr == 3'b110); + + // read/write memory combi logic + assign read_mem_combi = (avl_mem_read && ~avl_mem_waitrequest); + assign write_mem_combi = (avl_mem_write && ~avl_mem_waitrequest); + + // read csr logic + assign read_status_combi = (avl_csr_read && access_csr_status && ~avl_csr_waitrequest); + assign read_sid_combi = (avl_csr_read && access_csr_sid && ~avl_csr_waitrequest); + assign read_rdid_combi = (avl_csr_read && access_csr_rdid && ~avl_csr_waitrequest); + assign read_isr_combi = (avl_csr_read && access_isr && ~avl_csr_waitrequest); + assign read_imr_combi = (avl_csr_read && access_imr && ~avl_csr_waitrequest); + assign write_isr_combi = (avl_csr_write && access_isr && ~avl_csr_waitrequest); + assign write_imr_combi = (avl_csr_write && access_imr && ~avl_csr_waitrequest); + assign write_sce_combi = (avl_csr_write && access_sce && ~avl_csr_waitrequest); + + // write csr logic + assign bulk_erase_combi = (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b01); + assign sector_erase_combi = (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b10); + assign sector_protect_combi = (avl_csr_write && access_csr_mem_op && ~avl_csr_waitrequest && avl_csr_wrdata[1:0] == 2'b11); + assign illegal_write_combi = (asmi_illegal_write) ? 1'b1 : + (write_isr_combi && avl_csr_wrdata[1]) ? 1'b0 : + illegal_write_reg; + assign illegal_erase_combi = (asmi_illegal_erase) ? 1'b1 : + (write_isr_combi && avl_csr_wrdata[0]) ? 1'b0 : + illegal_erase_reg; + assign m_illegal_write_combi= (write_imr_combi) ? avl_csr_wrdata[1] : m_illegal_write_reg; + assign m_illegal_erase_combi= (write_imr_combi) ? avl_csr_wrdata[0] : m_illegal_erase_reg; + assign wren_combi = (sector_protect_combi || sector_erase_combi || bulk_erase_combi); + + assign asmi_rden = (rd_burstcount_cnt > 9'd0); // deasserted at the last 2 byte - refer to ASMI_PARALLEL UG + + // interrupt signal + assign irq = (illegal_write_reg && m_illegal_write_reg) || (illegal_erase_reg && m_illegal_erase_reg); + + assign last_wr_byte = (wr_burstcount_cnt == wr_mem_burstcount - 9'd1) ? 1'b1 : 1'b0; + + assign asmi_wren = wren_internal || asmi_en4b_addr || asmi_shift_bytes || asmi_write; + + assign data_valid_combi = (rd_burstcount_cnt[1:0] == 2'b00) ? asmi_data_valid : 1'b0; + + assign wfifo_data_in_0 = {avl_mem_byteenable[0], avl_mem_wrdata[7:0] }; + assign wfifo_data_in_1 = {avl_mem_byteenable[1], avl_mem_wrdata[15:8] }; + assign wfifo_data_in_2 = {avl_mem_byteenable[2], avl_mem_wrdata[23:16] }; + assign wfifo_data_in_3 = {avl_mem_byteenable[3], avl_mem_wrdata[31:24] }; + + assign avl_mem_rddata = {rd_data_reg[3], rd_data_reg[2], rd_data_reg[1], rd_data_reg[0]}; + assign pending_wr_data = (|wr_data_reg_full) ? 1'b1 : 1'b0; + assign detect_addroffset = (pending_wr_data && wr_data_reg[wr_cnt][8]) ? 1'b1 : + (wr_burstcount_cnt == {9{1'b0}}) ? 1'b0 : detect_addroffset_reg; + + //-------------------------------- array to store write data ------------------------------------- + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + wr_data_reg <= '{{9{1'b0}}, {9{1'b0}}, {9{1'b0}}, {9{1'b0}}}; + wr_data_reg_full <= {4{1'b0}}; + end + else if (write_mem_combi) begin + wr_data_reg <= {wfifo_data_in_3, wfifo_data_in_2, wfifo_data_in_1, wfifo_data_in_0}; + wr_data_reg_full <= {4{1'b1}}; + end + else if (wr_data_reg_full > 4'b0000) begin + wr_data_reg_full <= wr_data_reg_full << 1; + end + end + + //-------------------------------- array to store read data ------------------------------------- + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + rd_data_reg <= '{{8{1'b0}}, {8{1'b0}}, {8{1'b0}}, {8{1'b0}}}; + rd_cnt <= {2{1'b0}}; + end + else if (asmi_data_valid) begin + rd_data_reg[rd_cnt] <= asmi_dataout; + rd_cnt <= rd_cnt + 2'b01; + end + end + + //------------------------------- Enable 4-byte addressing out of reset ---------------------- + generate + if (ENABLE_4BYTE_ADDR) begin + typedef enum logic[1:0] {EN4B_CHIP1, EN4B_CHIP2, EN4B_CHIP3, IDLE} state_t; + state_t state; + + always @(posedge clk or negedge reset_n_reg) begin // use reset_n_reg because user is allow to send cmd to ASMI_PARALLEL 2 clock cycles after reset + if (~reset_n_reg) begin + state <= EN4B_CHIP1; + asmi_en4b_addr <= 1'b1; + temp_sce <= 3'b001; + end + else begin + case (state) + EN4B_CHIP1 : begin + asmi_en4b_addr <= 1'b1; + if (~asmi_busy) begin + if (CHIP_SELS > 1) begin + state <= EN4B_CHIP2; + temp_sce <= 3'b010; + end + else begin + state <= IDLE; + temp_sce <= 3'b000; + end + end + end + EN4B_CHIP2 : begin + asmi_en4b_addr <= 1'b1; + if (~asmi_busy) begin + if (CHIP_SELS > 2) begin + state <= EN4B_CHIP3; + temp_sce <= 3'b100; + end + else begin + state <= IDLE; + temp_sce <= 3'b000; + end + end + end + EN4B_CHIP3 : begin + asmi_en4b_addr <= 1'b1; + if (~asmi_busy) begin + state <= IDLE; + temp_sce <= 3'b000; + end + end + IDLE : begin + asmi_en4b_addr <= 1'b0; + state <= IDLE; + temp_sce <= 3'b000; + end + default : begin + asmi_en4b_addr <= 1'b0; + state <= IDLE; + temp_sce <= 3'b000; + end + endcase + end + end + end + else begin + always @(posedge clk) begin + asmi_en4b_addr <= 1'b0; + temp_sce <= 3'b000; + end + end + endgenerate + + //--------------------------------------- Waitrequest logic ---------------------------------- + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + wr_mem_waitrequest <= 1'b0; + local_waitrequest <= 1'b0; + end + else begin + if (read_mem_combi || read_status_combi || read_sid_combi || read_rdid_combi || bulk_erase_combi || sector_erase_combi || sector_protect_combi || asmi_en4b_addr) begin // no back pressure during imr & isr access + local_waitrequest <= 1'b1; + end + else if (asmi_busy_reg && ~asmi_busy) begin + local_waitrequest <= 1'b0; + end + + if (write_mem_combi) begin + wr_mem_waitrequest <= 1'b1; + end + else if ((~pending_wr_data && ~asmi_write) || asmi_busy_reg && ~asmi_busy) begin + wr_mem_waitrequest <= 1'b0; + end + end + end + + // -------------------------------------- MEM ACCESS ----------------------------------------- + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + rd_mem_burstcount <= {9{1'b0}}; + wr_mem_burstcount <= {9{1'b0}}; + wr_mem_addr <= {LOCAL_ADDR_WIDTH{1'b0}}; + end + else begin + if (read_mem_combi) begin + rd_mem_burstcount <= {avl_mem_burstcount, 2'b00}; + end + if (write_mem_combi && (wr_burstcount_cnt == {9{1'b0}})) begin + wr_mem_addr <= {temp_mem_addr, 2'b00}; + wr_mem_burstcount <= {avl_mem_burstcount, 2'b00}; + end + end + end + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + wr_burstcount_cnt <= {9{1'b0}}; + end + else begin + if (pending_wr_data) begin + wr_burstcount_cnt <= wr_burstcount_cnt + 9'd1; + end + else if (wr_burstcount_cnt == wr_mem_burstcount) begin + wr_burstcount_cnt <= {9{1'b0}}; + end + end + end + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + rd_burstcount_cnt <= {9{1'b0}}; + end + else begin + if (read_mem_combi) begin + rd_burstcount_cnt <= 9'd1; + end + else if (rd_burstcount_cnt == rd_mem_burstcount) begin // each rd 4 burst + rd_burstcount_cnt <= {9{1'b0}}; + end + else if (asmi_data_valid && rd_burstcount_cnt > 0) begin + rd_burstcount_cnt <= rd_burstcount_cnt + 9'd1; + end + end + end + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + asmi_addr <= {ASMI_ADDR_WIDTH{1'b0}}; + end + else begin + if (sector_erase_combi) begin // set lower 16 bits to zero so that erase at starting address of each sector + asmi_addr <= {avl_csr_wrdata[LAST_ADDR_BIT : 8], {16{1'b0}}}; + end + if (read_mem_combi) begin + asmi_addr <= {temp_mem_addr, 2'b00}; + end + + if (detect_addroffset && ~detect_addroffset_reg) begin + asmi_addr <= wr_mem_addr + {{LOCAL_ADDR_WIDTH-9{1'b0}}, wr_burstcount_cnt}; + end + + end + end + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + asmi_datain <= {8{1'b0}}; + wr_cnt <= {2{1'b0}}; + asmi_shift_bytes <= 1'b0; + end + else begin + if (sector_protect_combi) begin + asmi_datain <= {{1{1'b0}}, avl_csr_wrdata[11], avl_csr_wrdata[12], avl_csr_wrdata[10:8], {2{1'b0}}}; // BP3, TB, BP2, BP1, BP0 + end + if (pending_wr_data) begin + asmi_datain <= wr_data_reg[wr_cnt][7:0]; + wr_cnt <= wr_cnt + 2'd1; + end + if (pending_wr_data && wr_data_reg[wr_cnt][8]) begin + asmi_shift_bytes <= 1'b1; + end + else begin + asmi_shift_bytes <= 1'b0; + end + end + end + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + asmi_read_status <= 1'b0; + asmi_read_sid <= 1'b0; + asmi_read_rdid <= 1'b0; + asmi_bulk_erase <= 1'b0; + asmi_sector_erase <= 1'b0; + asmi_sector_protect <= 1'b0; + wren_internal <= 1'b0; + asmi_write <= 1'b0; + asmi_fast_read <= 1'b0; + asmi_busy_reg <= 1'b0; + avl_mem_rddata_valid <= 1'b0; + detect_addroffset_reg <= 1'b0; + reset_n_reg <= 1'b0; + end + else begin + asmi_read_status <= read_status_combi; + asmi_read_sid <= read_sid_combi; + asmi_read_rdid <= read_rdid_combi; + asmi_bulk_erase <= bulk_erase_combi; + asmi_sector_erase <= sector_erase_combi; + asmi_sector_protect <= sector_protect_combi; + wren_internal <= wren_combi; + asmi_write <= last_wr_byte; + asmi_fast_read <= read_mem_combi; + asmi_busy_reg <= asmi_busy; + avl_mem_rddata_valid <= data_valid_combi; + detect_addroffset_reg <= detect_addroffset; + reset_n_reg <= 1'b1; + end + end + + // --------------------------------------------- CSR ACCESS ------------------------------------- + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + illegal_write_reg <= 1'b0; + illegal_erase_reg <= 1'b0; + m_illegal_write_reg <= 1'b0; + m_illegal_erase_reg <= 1'b0; + end + else begin + illegal_write_reg <= illegal_write_combi; + illegal_erase_reg <= illegal_erase_combi; + m_illegal_write_reg <= m_illegal_write_combi; + m_illegal_erase_reg <= m_illegal_erase_combi; + end + end + + // csr read only registers enable logic + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + read_status_en <= 1'b0; + read_sid_en <= 1'b0; + read_rdid_en <= 1'b0; + end + else if (asmi_read_status) begin + read_status_en <= 1'b1; + end + else if (asmi_read_sid) begin + read_sid_en <= 1'b1; + end + else if (asmi_read_rdid) begin + read_rdid_en <= 1'b1; + end + else if (asmi_busy == 0) begin + read_status_en <= 1'b0; + read_sid_en <= 1'b0; + read_rdid_en <= 1'b0; + end + end + + // generation logic for avl csr read data valid + assign avl_csr_rddata_valid = read_status_valid || read_sid_valid || read_rdid_valid || read_isr_valid || read_imr_valid; + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + read_status_valid <= 1'b0; + read_sid_valid <= 1'b0; + read_rdid_valid <= 1'b0; + read_isr_valid <= 1'b0; + read_imr_valid <= 1'b0; + end + else begin + if (read_status_en && asmi_busy == 0) begin + read_status_valid <= 1'b1; + end + else begin + read_status_valid <= 1'b0; + end + + if (read_sid_en && asmi_busy == 0) begin + read_sid_valid <= 1'b1; + end + else begin + read_sid_valid <= 1'b0; + end + + if (read_rdid_en && asmi_busy == 0) begin + read_rdid_valid <= 1'b1; + end + else begin + read_rdid_valid <= 1'b0; + end + + if (read_isr_combi) begin + read_isr_valid <= 1'b1; + end + else begin + read_isr_valid <= 1'b0; + end + + if (read_imr_combi) begin + read_imr_valid <= 1'b1; + end + else begin + read_imr_valid <= 1'b0; + end + end + end + + // generation logic for avl csr read data + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + avl_csr_rddata <= {CSR_DATA_WIDTH{1'b0}}; + end + else begin + if (read_status_en && asmi_busy == 0) begin + avl_csr_rddata <= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_status_out}; + end + if (read_sid_en && asmi_busy == 0) begin + avl_csr_rddata <= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_epcs_id}; + end + if (read_rdid_en && asmi_busy == 0) begin + avl_csr_rddata <= {{CSR_DATA_WIDTH-8{1'b0}}, asmi_rdid_out}; + end + if (read_isr_combi) begin + avl_csr_rddata <= {{CSR_DATA_WIDTH-2{1'b0}}, illegal_write_reg, illegal_erase_reg}; + end + if (read_imr_combi) begin + avl_csr_rddata <= {{CSR_DATA_WIDTH-2{1'b0}}, m_illegal_write_reg, m_illegal_erase_reg}; + end + end + end + + +endmodule diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller_arb.sv b/ip/altera_epcq_controller_mod/altera_epcq_controller_arb.sv new file mode 100644 index 0000000..41d9481 --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller_arb.sv @@ -0,0 +1,230 @@ +// (C) 2001-2015 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +// (C) 2001-2014 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + +`timescale 1ps / 1ps + +module altera_epcq_controller_arb #( + parameter CS_WIDTH = 1, + parameter ENABLE_4BYTE_ADDR = 1, + parameter ADDR_WIDTH = 22, + parameter ASI_WIDTH = 1, + parameter DEVICE_FAMILY = "CYCLONE V", + parameter ASMI_ADDR_WIDTH = 22, + parameter CHIP_SELS = 1 +)( + input wire clk, + input wire reset_n, + + // ports to access csr + input wire avl_csr_write, + input wire avl_csr_read, + input wire [2:0] avl_csr_addr, + input wire [31:0] avl_csr_wrdata, + output reg [31:0] avl_csr_rddata, + output reg avl_csr_rddata_valid, + output reg avl_csr_waitrequest, + + // ports to access memory + input wire avl_mem_write, + input wire avl_mem_read, + input wire [ADDR_WIDTH-1:0] avl_mem_addr, + input wire [31:0] avl_mem_wrdata, + input wire [3:0] avl_mem_byteenable, + input wire [6:0] avl_mem_burstcount, + output wire [31:0] avl_mem_rddata, + output reg avl_mem_rddata_valid, + output reg avl_mem_waitrequest, + + // interrupt signal + output reg irq, + + // Disable dedicated active serial interface + input wire [ASI_WIDTH-1:0] epcq_dataout, + output reg epcq_dclk, + output reg [CS_WIDTH-1:0] epcq_scein, + output reg [ASI_WIDTH-1:0] epcq_sdoin, + output reg [ASI_WIDTH-1:0] epcq_dataoe, + + // ASMI PARALLEL interface + input wire [ASI_WIDTH-1:0] ddasi_dataoe, + output reg [ASI_WIDTH-1:0] ddasi_dataout, + input wire ddasi_dclk, + input wire [CS_WIDTH-1:0] ddasi_scein, + input reg [ASI_WIDTH-1:0] ddasi_sdoin, + + input wire asmi_busy, + input wire asmi_data_valid, + input wire [7:0] asmi_dataout, + output reg asmi_clkin, + output reg asmi_reset, + output reg [CS_WIDTH-1:0] asmi_sce, + output reg [ASMI_ADDR_WIDTH-1:0] asmi_addr, + output reg [7:0] asmi_datain, + output reg asmi_fast_read, + output wire asmi_rden, + output reg asmi_shift_bytes, + output reg asmi_en4b_addr, + output wire asmi_wren, + output reg asmi_write, + + input wire asmi_illegal_erase, + input wire asmi_illegal_write, + input wire [7:0] asmi_rdid_out, + input wire [7:0] asmi_status_out, + input wire [7:0] asmi_epcs_id, + output reg asmi_read_rdid, + output reg asmi_read_status, + output reg asmi_read_sid, + output reg asmi_bulk_erase, + output reg asmi_sector_erase, + output reg asmi_sector_protect +); + + reg temp_mem_write, temp_mem_read, mem_write, mem_read, back_pressured_ctrl; + reg [ADDR_WIDTH-1:0] temp_mem_addr, mem_addr; + reg [31:0] temp_mem_wrdata, mem_wrdata; + reg [3:0] temp_mem_byteenable, mem_byteenable; + reg [6:0] temp_mem_burstcount, mem_burstcount; + + wire back_pressured, temp_csr_waitrequest, temp_mem_waitrequest; + + //-------------------- Arbitration logic between avalon csr and mem interface ----------- + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + back_pressured_ctrl <= 1'b0; + end + else if (back_pressured) begin + back_pressured_ctrl <= 1'b1; + end + else if (~temp_csr_waitrequest) begin + back_pressured_ctrl <= 1'b0; + end + end + + always @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + mem_write <= 1'b0; + mem_read <= 1'b0; + mem_addr <= {ADDR_WIDTH{1'b0}}; + mem_wrdata <= {32{1'b0}}; + mem_byteenable <= {4{1'b0}}; + mem_burstcount <= {7{1'b0}}; + end + else if ((avl_csr_write || avl_csr_read) && ~avl_csr_waitrequest && (avl_mem_write || avl_mem_read) && ~avl_mem_waitrequest) begin + // to back pressure master + mem_write <= avl_mem_write; + mem_read <= avl_mem_read; + mem_addr <= avl_mem_addr; + mem_wrdata <= avl_mem_wrdata; + mem_byteenable <= avl_mem_byteenable; + mem_burstcount <= avl_mem_burstcount; + end + end + + assign back_pressured = ((avl_csr_write || avl_csr_read) && ~temp_csr_waitrequest && (avl_mem_write || avl_mem_read)) ? 1'b1 : 1'b0; // to back pressure controller + assign avl_csr_waitrequest = (~avl_csr_write && ~avl_csr_read && back_pressured_ctrl) ? 1'b1 : temp_csr_waitrequest; + assign avl_mem_waitrequest = (back_pressured_ctrl) ? 1'b1 : temp_mem_waitrequest; + assign temp_mem_write = (back_pressured) ? 1'b0 : + (back_pressured_ctrl) ? mem_write : avl_mem_write; + assign temp_mem_read = (back_pressured) ? 1'b0 : + (back_pressured_ctrl) ? mem_read : avl_mem_read; + assign temp_mem_addr = (back_pressured) ? {ADDR_WIDTH{1'b0}} : + (back_pressured_ctrl) ? mem_addr : avl_mem_addr; + assign temp_mem_wrdata = (back_pressured) ? {32{1'b0}} : + (back_pressured_ctrl) ? mem_wrdata : avl_mem_wrdata; + assign temp_mem_byteenable = (back_pressured) ? {4{1'b0}} : + (back_pressured_ctrl) ? mem_byteenable : avl_mem_byteenable; + assign temp_mem_burstcount = (back_pressured) ? {7{1'b0}} : + (back_pressured_ctrl) ? mem_burstcount : avl_mem_burstcount; + + + //---------------------------------------------------------------------------------------// + + altera_epcq_controller #( + .CS_WIDTH (CS_WIDTH), + .DEVICE_FAMILY (DEVICE_FAMILY), + .ADDR_WIDTH (ADDR_WIDTH), + .ASMI_ADDR_WIDTH (ASMI_ADDR_WIDTH), + .ASI_WIDTH (ASI_WIDTH), + .CHIP_SELS (CHIP_SELS), + .ENABLE_4BYTE_ADDR (ENABLE_4BYTE_ADDR) + ) controller ( + .clk (clk), + .reset_n (reset_n), + .avl_csr_read (avl_csr_read), + .avl_csr_waitrequest (temp_csr_waitrequest), + .avl_csr_write (avl_csr_write), + .avl_csr_addr (avl_csr_addr), + .avl_csr_wrdata (avl_csr_wrdata), + .avl_csr_rddata (avl_csr_rddata), + .avl_csr_rddata_valid (avl_csr_rddata_valid), + .avl_mem_write (temp_mem_write), + .avl_mem_burstcount (temp_mem_burstcount), + .avl_mem_waitrequest (temp_mem_waitrequest), + .avl_mem_read (temp_mem_read), + .avl_mem_addr (temp_mem_addr), + .avl_mem_wrdata (temp_mem_wrdata), + .avl_mem_byteenable (temp_mem_byteenable), + .avl_mem_rddata (avl_mem_rddata), + .avl_mem_rddata_valid (avl_mem_rddata_valid), + .asmi_status_out (asmi_status_out), + .asmi_epcs_id (asmi_epcs_id), + .asmi_illegal_erase (asmi_illegal_erase), + .asmi_illegal_write (asmi_illegal_write), + .ddasi_dataoe (ddasi_dataoe), + .ddasi_dclk (ddasi_dclk), + .ddasi_scein (ddasi_scein), + .ddasi_sdoin (ddasi_sdoin), + .asmi_busy (asmi_busy), + .asmi_data_valid (asmi_data_valid), + .asmi_dataout (asmi_dataout), + .epcq_dataout (epcq_dataout), + .ddasi_dataout (ddasi_dataout), + .asmi_read_rdid (asmi_read_rdid), + .asmi_read_status (asmi_read_status), + .asmi_read_sid (asmi_read_sid), + .asmi_bulk_erase (asmi_bulk_erase), + .asmi_sector_erase (asmi_sector_erase), + .asmi_sector_protect (asmi_sector_protect), + .epcq_dclk (epcq_dclk), + .epcq_scein (epcq_scein), + .epcq_sdoin (epcq_sdoin), + .epcq_dataoe (epcq_dataoe), + .asmi_clkin (asmi_clkin), + .asmi_reset (asmi_reset), + .asmi_sce (asmi_sce), + .asmi_addr (asmi_addr), + .asmi_datain (asmi_datain), + .asmi_fast_read (asmi_fast_read), + .asmi_rden (asmi_rden), + .asmi_shift_bytes (asmi_shift_bytes), + .asmi_wren (asmi_wren), + .asmi_write (asmi_write), + .asmi_rdid_out (asmi_rdid_out), + .asmi_en4b_addr (asmi_en4b_addr), + .irq (irq) + ); + +endmodule diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller_fifo.v b/ip/altera_epcq_controller_mod/altera_epcq_controller_fifo.v new file mode 100644 index 0000000..6e4c212 --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller_fifo.v @@ -0,0 +1,176 @@ +// (C) 2001-2015 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +// megafunction wizard: %FIFO% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: scfifo + +// ============================================================ +// File Name: altera_epcq_controller_fifo.v +// Megafunction Name(s): +// scfifo +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 14.1.0 Internal Build 64 05/14/2014 PN Full Version +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus II License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module altera_epcq_controller_fifo #( + parameter DEVICE_FAMILY = "CYCLONE V", + parameter MEMORY_TYPE = "RAM_BLOCK_TYPE=MLAB" +)( + clock, + data, + rdreq, + wrreq, + empty, + full, + q); + + input clock; + input [35:0] data; + input rdreq; + input wrreq; + output empty; + output full; + output [35:0] q; + + wire sub_wire0; + wire sub_wire1; + wire [35:0] sub_wire2; + wire empty = sub_wire0; + wire full = sub_wire1; + wire [35:0] q = sub_wire2[35:0]; + + scfifo scfifo_component ( + .clock (clock), + .data (data), + .rdreq (rdreq), + .wrreq (wrreq), + .empty (sub_wire0), + .full (sub_wire1), + .q (sub_wire2), + .aclr (), + .almost_empty (), + .almost_full (), + .sclr (), + .usedw ()); + defparam + scfifo_component.add_ram_output_register = "OFF", + scfifo_component.intended_device_family = DEVICE_FAMILY, + scfifo_component.lpm_hint = MEMORY_TYPE, + scfifo_component.lpm_numwords = 1024, + scfifo_component.lpm_showahead = "ON", + scfifo_component.lpm_type = "scfifo", + scfifo_component.lpm_width = 36, + scfifo_component.lpm_widthu = 10, + scfifo_component.overflow_checking = "ON", + scfifo_component.underflow_checking = "ON", + scfifo_component.use_eab = "ON"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" +// Retrieval info: PRIVATE: Clock NUMERIC "0" +// Retrieval info: PRIVATE: Depth NUMERIC "1024" +// Retrieval info: PRIVATE: Empty NUMERIC "1" +// Retrieval info: PRIVATE: Full NUMERIC "1" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV GX" +// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" +// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" +// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" +// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0" +// Retrieval info: PRIVATE: Optimize NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0" +// Retrieval info: PRIVATE: UsedW NUMERIC "0" +// Retrieval info: PRIVATE: Width NUMERIC "8" +// Retrieval info: PRIVATE: dc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: diff_widths NUMERIC "0" +// Retrieval info: PRIVATE: msb_usedw NUMERIC "0" +// Retrieval info: PRIVATE: output_width NUMERIC "8" +// Retrieval info: PRIVATE: rsEmpty NUMERIC "1" +// Retrieval info: PRIVATE: rsFull NUMERIC "0" +// Retrieval info: PRIVATE: rsUsedW NUMERIC "0" +// Retrieval info: PRIVATE: sc_aclr NUMERIC "0" +// Retrieval info: PRIVATE: sc_sclr NUMERIC "0" +// Retrieval info: PRIVATE: wsEmpty NUMERIC "0" +// Retrieval info: PRIVATE: wsFull NUMERIC "1" +// Retrieval info: PRIVATE: wsUsedW NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV GX" +// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M9K" +// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024" +// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" +// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo" +// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8" +// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10" +// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON" +// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON" +// Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock" +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" +// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty" +// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq" +// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq" +// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0 +// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 +// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 +// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0 +// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller_hw.tcl b/ip/altera_epcq_controller_mod/altera_epcq_controller_hw.tcl new file mode 100644 index 0000000..b13a6ef --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller_hw.tcl @@ -0,0 +1,453 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# TCL File Generated by Component Editor 14.1 +# Fri May 09 18:08:10 MYT 2014 +# DO NOT MODIFY + + +# +# altera_epcq_controller_core "Altera EPCQ Serial Flash controller core" v14.1 +# Altera Coorperation 2014.05.23.15:01:29 +# This component is a serial flash controller which allows user to access Altera EPCQ devices +# + +# +# request TCL package from ACDS 14.1 +# +package require -exact qsys 14.1 + + + +# +# module altera_epcq_controller +# +set_module_property DESCRIPTION "This component is a serial flash controller which allows user to access Altera EPCQ devices" +set_module_property NAME altera_epcq_controller_core +set_module_property VERSION 15.1 +set_module_property INTERNAL true +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property AUTHOR "Altera Corporation" +set_module_property DISPLAY_NAME "Altera EPCQ Serial Flash controller core" +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property HIDE_FROM_QUARTUS true +set_module_property EDITABLE true +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false +set_module_property VALIDATION_CALLBACK "validate" +# +# file sets +# +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" +set_fileset_property QUARTUS_SYNTH TOP_LEVEL altera_epcq_controller_arb +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false +add_fileset_file altera_epcq_controller_arb.sv SYSTEM_VERILOG PATH altera_epcq_controller_arb.sv TOP_LEVEL_FILE +add_fileset_file altera_epcq_controller.sv SYSTEM_VERILOG PATH altera_epcq_controller.sv + +add_fileset SIM_VERILOG SIM_VERILOG "" "" +set_fileset_property SIM_VERILOG TOP_LEVEL altera_epcq_controller_arb +set_fileset_property SIM_VERILOG ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property SIM_VERILOG ENABLE_FILE_OVERWRITE_MODE true +add_fileset_file altera_epcq_controller_arb.sv SYSTEM_VERILOG PATH altera_epcq_controller_arb.sv TOP_LEVEL_FILE +add_fileset_file altera_epcq_controller.sv SYSTEM_VERILOG PATH altera_epcq_controller.sv + +# +# add system info parameter +add_parameter deviceFeaturesSystemInfo STRING "None" +set_parameter_property deviceFeaturesSystemInfo system_info "DEVICE_FEATURES" +set_parameter_property deviceFeaturesSystemInfo VISIBLE false + +# +# parameters +# +add_parameter DEVICE_FAMILY STRING "" +set_parameter_property DEVICE_FAMILY SYSTEM_INFO "DEVICE_FAMILY" +set_parameter_property DEVICE_FAMILY HDL_PARAMETER true +set_parameter_property DEVICE_FAMILY VISIBLE false + +add_parameter ADDR_WIDTH INTEGER 19 +set_parameter_property ADDR_WIDTH DEFAULT_VALUE 19 +set_parameter_property ADDR_WIDTH DISPLAY_NAME ADDR_WIDTH +set_parameter_property ADDR_WIDTH DERIVED true +set_parameter_property ADDR_WIDTH TYPE INTEGER +set_parameter_property ADDR_WIDTH VISIBLE false +set_parameter_property ADDR_WIDTH UNITS None +set_parameter_property ADDR_WIDTH ALLOWED_RANGES {19, 20, 21, 22, 23, 24, 25, 26, 27, 28} +set_parameter_property ADDR_WIDTH HDL_PARAMETER true + +add_parameter ASMI_ADDR_WIDTH INTEGER 24 +set_parameter_property ASMI_ADDR_WIDTH DEFAULT_VALUE 24 +set_parameter_property ASMI_ADDR_WIDTH DISPLAY_NAME ASMI_ADDR_WIDTH +set_parameter_property ASMI_ADDR_WIDTH DERIVED true +set_parameter_property ASMI_ADDR_WIDTH TYPE INTEGER +set_parameter_property ASMI_ADDR_WIDTH VISIBLE false +set_parameter_property ASMI_ADDR_WIDTH UNITS None +set_parameter_property ASMI_ADDR_WIDTH ALLOWED_RANGES {24, 32} +set_parameter_property ASMI_ADDR_WIDTH HDL_PARAMETER true + +add_parameter ASI_WIDTH INTEGER 1 +set_parameter_property ASI_WIDTH DEFAULT_VALUE 1 +set_parameter_property ASI_WIDTH DISPLAY_NAME ASI_WIDTH +set_parameter_property ASI_WIDTH DERIVED true +set_parameter_property ASI_WIDTH TYPE INTEGER +set_parameter_property ASI_WIDTH VISIBLE false +set_parameter_property ASI_WIDTH UNITS None +set_parameter_property ASI_WIDTH ALLOWED_RANGES {1, 4} +set_parameter_property ASI_WIDTH HDL_PARAMETER true + +add_parameter CS_WIDTH INTEGER 1 +set_parameter_property CS_WIDTH DEFAULT_VALUE 1 +set_parameter_property CS_WIDTH DISPLAY_NAME CS_WIDTH +set_parameter_property CS_WIDTH DERIVED true +set_parameter_property CS_WIDTH TYPE INTEGER +set_parameter_property CS_WIDTH VISIBLE false +set_parameter_property CS_WIDTH UNITS None +set_parameter_property CS_WIDTH ALLOWED_RANGES {1, 3} +set_parameter_property CS_WIDTH HDL_PARAMETER true + +add_parameter CHIP_SELS INTEGER "1" +set_parameter_property CHIP_SELS DISPLAY_NAME "Number of Chip Selects used" +set_parameter_property CHIP_SELS ALLOWED_RANGES {1 2 3} +set_parameter_property CHIP_SELS DESCRIPTION "Number of EPCQ(L) devices that are attached and need a CHIPSEL" +set_parameter_property CHIP_SELS HDL_PARAMETER true +set_parameter_property CHIP_SELS AFFECTS_GENERATION true + +add_parameter DDASI INTEGER "0" +set_parameter_property DDASI DISPLAY_NAME "Disable dedicated Active Serial interface" +set_parameter_property DDASI DESCRIPTION "Check to route ASMIBLOCK signals to top level of design" +set_parameter_property DDASI AFFECTS_GENERATION true +set_parameter_property DDASI VISIBLE false +set_parameter_property DDASI DERIVED false + +add_parameter ENABLE_4BYTE_ADDR INTEGER "0" +set_parameter_property ENABLE_4BYTE_ADDR DISPLAY_NAME "Enable 4-byte addressing mode" +set_parameter_property ENABLE_4BYTE_ADDR DESCRIPTION "Check to enable 4-byte addressing mode for device larger than 128Mbyte" +set_parameter_property ENABLE_4BYTE_ADDR AFFECTS_GENERATION true +set_parameter_property ENABLE_4BYTE_ADDR VISIBLE false +set_parameter_property ENABLE_4BYTE_ADDR HDL_PARAMETER true +set_parameter_property ENABLE_4BYTE_ADDR DERIVED true + +# SPI device selection +add_parameter FLASH_TYPE STRING "EPCQ16" +set_parameter_property FLASH_TYPE DISPLAY_NAME "Configuration device type" +set_parameter_property FLASH_TYPE DESCRIPTION "Select targeted EPCS/EPCQ devices" +set_parameter_property FLASH_TYPE AFFECTS_GENERATION true +set_parameter_property FLASH_TYPE VISIBLE true +set_parameter_property FLASH_TYPE DERIVED false + +add_parameter IO_MODE STRING "STANDARD" +set_parameter_property IO_MODE DISPLAY_NAME "Choose I/O mode" +set_parameter_property IO_MODE ALLOWED_RANGES {"STANDARD" "QUAD"} +set_parameter_property IO_MODE DESCRIPTION "Select extended data width when Fast Read operation is enabled" + +# +# display items +# + + +# +# connection point clock_sink +# +add_interface clock_sink clock end +set_interface_property clock_sink clockRate 0 +set_interface_property clock_sink ENABLED true +set_interface_property clock_sink EXPORT_OF "" +set_interface_property clock_sink PORT_NAME_MAP "" +set_interface_property clock_sink CMSIS_SVD_VARIABLES "" +set_interface_property clock_sink SVD_ADDRESS_GROUP "" + +add_interface_port clock_sink clk clk Input 1 + + +# +# connection point reset +# +add_interface reset reset end +set_interface_property reset associatedClock clock_sink +set_interface_property reset synchronousEdges DEASSERT +set_interface_property reset ENABLED true +set_interface_property reset EXPORT_OF "" +set_interface_property reset PORT_NAME_MAP "" +set_interface_property reset CMSIS_SVD_VARIABLES "" +set_interface_property reset SVD_ADDRESS_GROUP "" + +add_interface_port reset reset_n reset_n Input 1 + + +# +# connection point avl_csr +# +add_interface avl_csr avalon end +set_interface_property avl_csr addressUnits WORDS +set_interface_property avl_csr associatedClock clock_sink +set_interface_property avl_csr associatedReset reset +set_interface_property avl_csr bitsPerSymbol 8 +set_interface_property avl_csr burstOnBurstBoundariesOnly false +set_interface_property avl_csr burstcountUnits WORDS +set_interface_property avl_csr explicitAddressSpan 0 +set_interface_property avl_csr holdTime 0 +set_interface_property avl_csr linewrapBursts false +set_interface_property avl_csr maximumPendingReadTransactions 1 +set_interface_property avl_csr maximumPendingWriteTransactions 0 +set_interface_property avl_csr readLatency 0 +set_interface_property avl_csr readWaitTime 0 +set_interface_property avl_csr setupTime 0 +set_interface_property avl_csr timingUnits Cycles +set_interface_property avl_csr writeWaitTime 0 +set_interface_property avl_csr ENABLED true +set_interface_property avl_csr EXPORT_OF "" +set_interface_property avl_csr PORT_NAME_MAP "" +set_interface_property avl_csr CMSIS_SVD_VARIABLES "" +set_interface_property avl_csr SVD_ADDRESS_GROUP "" + +add_interface_port avl_csr avl_csr_read read Input 1 +add_interface_port avl_csr avl_csr_waitrequest waitrequest Output 1 +add_interface_port avl_csr avl_csr_write write Input 1 +add_interface_port avl_csr avl_csr_addr address Input 3 +add_interface_port avl_csr avl_csr_wrdata writedata Input 32 +add_interface_port avl_csr avl_csr_rddata readdata Output 32 +add_interface_port avl_csr avl_csr_rddata_valid readdatavalid Output 1 + + +# +# connection point avl_mem +# +add_interface avl_mem avalon end +set_interface_property avl_mem addressUnits WORDS +set_interface_property avl_mem associatedClock clock_sink +set_interface_property avl_mem associatedReset reset +set_interface_property avl_mem bitsPerSymbol 8 +set_interface_property avl_mem burstOnBurstBoundariesOnly false +set_interface_property avl_mem burstcountUnits WORDS +set_interface_property avl_mem explicitAddressSpan 0 +set_interface_property avl_mem holdTime 0 +set_interface_property avl_mem linewrapBursts true +set_interface_property avl_mem maximumPendingReadTransactions 1 +set_interface_property avl_mem maximumPendingWriteTransactions 0 +set_interface_property avl_mem constantBurstBehavior true +set_interface_property avl_mem readLatency 0 +set_interface_property avl_mem readWaitTime 0 +set_interface_property avl_mem setupTime 0 +set_interface_property avl_mem timingUnits Cycles +set_interface_property avl_mem writeWaitTime 0 +set_interface_property avl_mem ENABLED true +set_interface_property avl_mem EXPORT_OF "" +set_interface_property avl_mem PORT_NAME_MAP "" +set_interface_property avl_mem CMSIS_SVD_VARIABLES "" +set_interface_property avl_mem SVD_ADDRESS_GROUP "" + +add_interface_port avl_mem avl_mem_write write Input 1 +add_interface_port avl_mem avl_mem_burstcount burstcount Input 7 +add_interface_port avl_mem avl_mem_waitrequest waitrequest Output 1 +add_interface_port avl_mem avl_mem_read read Input 1 +add_interface_port avl_mem avl_mem_addr address Input ADDR_WIDTH +add_interface_port avl_mem avl_mem_wrdata writedata Input 32 +add_interface_port avl_mem avl_mem_rddata readdata Output 32 +add_interface_port avl_mem avl_mem_rddata_valid readdatavalid Output 1 +add_interface_port avl_mem avl_mem_byteenable byteenable Input 4 + + +# +# connection point conduit_out +# +add_interface asmi_status_out conduit end +add_interface_port asmi_status_out asmi_status_out conduit_status_out Input 8 + +add_interface asmi_epcs_id conduit end +add_interface_port asmi_epcs_id asmi_epcs_id conduit_epcs_id Input 8 + +add_interface asmi_illegal_erase conduit end +add_interface_port asmi_illegal_erase asmi_illegal_erase conduit_illegal_erase Input 1 + +add_interface asmi_illegal_write conduit end +add_interface_port asmi_illegal_write asmi_illegal_write conduit_illegal_write Input 1 + +add_interface ddasi_dataoe conduit end +add_interface_port ddasi_dataoe ddasi_dataoe conduit_ddasi_dataoe Input ASI_WIDTH + +add_interface ddasi_dclk conduit end +add_interface_port ddasi_dclk ddasi_dclk conduit_ddasi_dclk Input 1 + +add_interface ddasi_scein conduit end +add_interface_port ddasi_scein ddasi_scein conduit_ddasi_scein Input CS_WIDTH + +add_interface ddasi_sdoin conduit end +add_interface_port ddasi_sdoin ddasi_sdoin conduit_ddasi_sdoin Input ASI_WIDTH + +add_interface asmi_busy conduit end +add_interface_port asmi_busy asmi_busy conduit_busy Input 1 + +add_interface asmi_data_valid conduit end +add_interface_port asmi_data_valid asmi_data_valid conduit_data_valid Input 1 + +add_interface asmi_dataout conduit end +add_interface_port asmi_dataout asmi_dataout conduit_dataout Input 8 + +add_interface epcq_dataout conduit end +add_interface_port epcq_dataout epcq_dataout conduit_epcq_dataout Input ASI_WIDTH + +add_interface ddasi_dataout conduit end +add_interface_port ddasi_dataout ddasi_dataout conduit_ddasi_dataout Output ASI_WIDTH + +add_interface asmi_read_rdid conduit end +add_interface_port asmi_read_rdid asmi_read_rdid conduit_read_rdid Output 1 + +add_interface asmi_read_status conduit end +add_interface_port asmi_read_status asmi_read_status conduit_read_status Output 1 + +add_interface asmi_read_sid conduit end +add_interface_port asmi_read_sid asmi_read_sid conduit_read_sid Output 1 + +add_interface asmi_bulk_erase conduit end +add_interface_port asmi_bulk_erase asmi_bulk_erase conduit_bulk_erase Output 1 + +add_interface asmi_sector_erase conduit end +add_interface_port asmi_sector_erase asmi_sector_erase conduit_sector_erase Output 1 + +add_interface asmi_sector_protect conduit end +add_interface_port asmi_sector_protect asmi_sector_protect conduit_sector_protect Output 1 + +add_interface epcq_dclk conduit end +add_interface_port epcq_dclk epcq_dclk conduit_epcq_dclk Output 1 + +add_interface epcq_scein conduit end +add_interface_port epcq_scein epcq_scein conduit_epcq_scein Output CS_WIDTH + +add_interface epcq_sdoin conduit end +add_interface_port epcq_sdoin epcq_sdoin conduit_epcq_sdoin Output ASI_WIDTH + +add_interface epcq_dataoe conduit end +add_interface_port epcq_dataoe epcq_dataoe conduit_epcq_dataoe Output ASI_WIDTH + +add_interface asmi_clkin conduit end +add_interface_port asmi_clkin asmi_clkin conduit_clkin Output 1 + +add_interface asmi_reset conduit end +add_interface_port asmi_reset asmi_reset conduit_reset Output 1 + +add_interface asmi_sce conduit end +add_interface_port asmi_sce asmi_sce conduit_asmi_sce Output CS_WIDTH + +add_interface asmi_addr conduit end +add_interface_port asmi_addr asmi_addr conduit_addr Output ASMI_ADDR_WIDTH + +add_interface asmi_datain conduit end +add_interface_port asmi_datain asmi_datain conduit_datain Output 8 + +add_interface asmi_fast_read conduit end +add_interface_port asmi_fast_read asmi_fast_read conduit_fast_read Output 1 + +add_interface asmi_rden conduit end +add_interface_port asmi_rden asmi_rden conduit_rden Output 1 + +add_interface asmi_shift_bytes conduit end +add_interface_port asmi_shift_bytes asmi_shift_bytes conduit_shift_bytes Output 1 + +add_interface asmi_wren conduit end +add_interface_port asmi_wren asmi_wren conduit_wren Output 1 + +add_interface asmi_write conduit end +add_interface_port asmi_write asmi_write conduit_write Output 1 + +add_interface asmi_rdid_out conduit end +add_interface_port asmi_rdid_out asmi_rdid_out conduit_rdid_out Input 8 + +add_interface asmi_en4b_addr conduit end +add_interface_port asmi_en4b_addr asmi_en4b_addr conduit_en4b_addr Output 1 + +# +# connection point interrupt_sender +# +add_interface interrupt_sender interrupt end +set_interface_property interrupt_sender associatedAddressablePoint avl_csr +set_interface_property interrupt_sender associatedClock clock_sink +set_interface_property interrupt_sender associatedReset reset +set_interface_property interrupt_sender bridgedReceiverOffset "" +set_interface_property interrupt_sender bridgesToReceiver "" +set_interface_property interrupt_sender ENABLED true +set_interface_property interrupt_sender EXPORT_OF "" +set_interface_property interrupt_sender PORT_NAME_MAP "" +set_interface_property interrupt_sender CMSIS_SVD_VARIABLES "" +set_interface_property interrupt_sender SVD_ADDRESS_GROUP "" + +add_interface_port interrupt_sender irq irq Output 1 + +proc validate {} { + set all_supported_SPI_list {"EPCS16" "EPCS64" "EPCS128" "EPCQ16" "EPCQ32" "EPCQ64" "EPCQ128" "EPCQ256" \ + "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024"} + + set_parameter_property FLASH_TYPE "ALLOWED_RANGES" $all_supported_SPI_list + set DEVICE_FAMILY [ get_parameter_value DEVICE_FAMILY ] + set CHIP_SELS [ get_parameter_value CHIP_SELS] + set temp_addr_width [ proc_get_derive_addr_width [ get_parameter_value FLASH_TYPE ] ] + set_parameter_value ENABLE_4BYTE_ADDR [ proc_get_derive_enable_2byte_addr [ get_parameter_value FLASH_TYPE ] ] + + if { [ get_parameter_value ENABLE_4BYTE_ADDR ] } { + set_parameter_value ASMI_ADDR_WIDTH 32 + } else { + set_parameter_value ASMI_ADDR_WIDTH 24 + } + + # check whether devices supporting multiple flash - only for Arria 10 + if {[check_device_family_equivalence $DEVICE_FAMILY "Arria 10"]} { + set is_multi_flash_support "true" + if {$CHIP_SELS eq 3 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 2]} + if {$CHIP_SELS eq 2 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 1]} + if {$CHIP_SELS eq 1 } {set_parameter_value ADDR_WIDTH $temp_addr_width } + } else { + set is_multi_flash_support "false" + set_parameter_value ADDR_WIDTH $temp_addr_width + } + +} + +proc proc_get_derive_enable_2byte_addr {flash_type} { + if { [ string match "*256*" "$flash_type" ] || [ string match "*512*" "$flash_type" ] || [ string match "*1024*" "$flash_type" ]} { + return true + } else { + return false + } +} + +proc proc_get_derive_addr_width {flash_type} { + switch $flash_type { + "EPCS16" - "EPCQ16" { + return 19 + } + "EPCS64" - "EPCQ64" { + return 21 + } + "EPCS128" - "EPCQ128" { + return 22 + } + "EPCQ32" { + return 20 + } + "EPCQ256" - "EPCQL256" { + return 23 + } + "EPCQ512" - "EPCQL512" { + return 24 + } + "EPCQL1024" { + return 25 + } + default { + # Should never enter this function + send_message error "$flash_type is not a valid flash type" + } + + } +} diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller_sw.tcl b/ip/altera_epcq_controller_mod/altera_epcq_controller_sw.tcl new file mode 100644 index 0000000..bfe4531 --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller_sw.tcl @@ -0,0 +1,58 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# +# altera_epcq_controller_sw.tcl +# + +# Create a new driver +create_driver altera_epcq_controller_mod_driver + +# Associate it with some hardware known as "altera_epcq_controller" +set_sw_property hw_class_name altera_epcq_controller_mod + +# The version of this driver +set_sw_property version 15.1 + +# This driver may be incompatible with versions of hardware less +# than specified below. Updates to hardware and device drivers +# rendering the driver incompatible with older versions of +# hardware are noted with this property assignment. +set_sw_property min_compatible_hw_version 14.1 + +# Initialize the driver in alt_sys_init() +set_sw_property auto_initialize true + +# This driver only works when the following combinations of interfaces +# are enabled and connected as a group of CSR interfaces. +set_sw_property csr_interfaces "avl_mem,avl_csr" + +# The EPCQ interrupt has an interrupt but it is not used in the driver. +# These assignments are still required by the Nios II SBT +set_sw_property isr_preemption_supported true +set_sw_property supported_interrupt_apis "legacy_interrupt_api enhanced_interrupt_api" + +# Location in generated BSP that above sources will be copied into +set_sw_property bsp_subdirectory drivers + +# Header files +add_sw_property include_source HAL/inc/altera_epcq_controller_mod.h +add_sw_property include_source inc/altera_epcq_controller_mod_regs.h + +# C/C++ source files +add_sw_property c_source HAL/src/altera_epcq_controller_mod.c + + +# This driver supports HAL & UCOSII BSP (OS) types +add_sw_property supported_bsp_type HAL +add_sw_property supported_bsp_type UCOSII diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper.sv.terp b/ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper.sv.terp new file mode 100644 index 0000000..3af20fc --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper.sv.terp @@ -0,0 +1,248 @@ +// (C) 2001-2015 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + + + +`timescale 1ps / 1ps + +${MULTICHIP} +${DDASI_ON} +${SID_EN} +${BULK_ERASE_EN} +${4BYTE_ADDR_EN} + +module altera_epcq_controller_wrapper #( + parameter CS_WIDTH = 1, + parameter DEVICE_FAMILY = "Arria V", + parameter ADDR_WIDTH = 24, + parameter ASI_WIDTH = 1, + parameter ENABLE_4BYTE_ADDR = 1, + parameter ASMI_ADDR_WIDTH = 22, + parameter CHIP_SELS = 1 +)( + input wire clk, + input wire reset_n, + + // ports to access csr + input wire avl_csr_write, + input wire avl_csr_read, + input wire [2:0] avl_csr_addr, + input wire [31:0] avl_csr_wrdata, + output wire [31:0] avl_csr_rddata, + output wire avl_csr_rddata_valid, + output wire avl_csr_waitrequest, + + // ports to access memory + input wire avl_mem_write, + input wire avl_mem_read, + input wire [ADDR_WIDTH-1:0] avl_mem_addr, + input wire [31:0] avl_mem_wrdata, + input wire [6:0] avl_mem_burstcount, + input wire [3:0] avl_mem_byteenable, + output wire [31:0] avl_mem_rddata, + output wire avl_mem_rddata_valid, + output wire avl_mem_waitrequest, + +`ifdef DDASI_ON + output wire [ASI_WIDTH-1:0] epcq_dataout, + output wire epcq_dclk, + output wire [CS_WIDTH-1:0] epcq_scein, + output wire [ASI_WIDTH-1:0] epcq_sdoin, + output wire [ASI_WIDTH-1:0] epcq_dataoe, +`endif + + // interrupt signal + output reg irq +); + +`ifdef DDASI_ON + wire [ASI_WIDTH-1:0] ddasi_dataoe; + wire [ASI_WIDTH-1:0] ddasi_dataout; + wire ddasi_dclk; + wire [CS_WIDTH-1:0] ddasi_scein; + wire [ASI_WIDTH-1:0] ddasi_sdoin; +`endif + wire asmi_busy; + wire asmi_data_valid; + wire [7:0] asmi_dataout; + wire asmi_clkin; + wire asmi_reset; +`ifdef MULTICHIP + wire [CS_WIDTH-1:0] asmi_sce; +`endif + wire [ASMI_ADDR_WIDTH-1:0] asmi_addr; + wire [7:0] asmi_datain; + wire asmi_fast_read; + wire asmi_rden; + wire asmi_shift_bytes; + wire asmi_wren; + wire asmi_write; + + wire asmi_illegal_erase; + wire asmi_illegal_write; + wire [7:0] asmi_rdid_out; + wire [7:0] asmi_status_out; +`ifdef ENABLE_SID + wire [7:0] asmi_epcs_id; +`endif + wire asmi_read_rdid; + wire asmi_read_status; + wire asmi_read_sid; +`ifdef ENABLE_4BYTE_ADDR_CODE + wire asmi_en4b_addr; +`endif +`ifdef ENABLE_BULK_ERASE + wire asmi_bulk_erase; +`endif + wire asmi_sector_erase; + wire asmi_sector_protect; + + altera_epcq_controller_core #( + .DEVICE_FAMILY (DEVICE_FAMILY), + .ADDR_WIDTH (ADDR_WIDTH), + .ASI_WIDTH (ASI_WIDTH), + .ASMI_ADDR_WIDTH (ASMI_ADDR_WIDTH), + .CS_WIDTH (CS_WIDTH), + .ENABLE_4BYTE_ADDR (ENABLE_4BYTE_ADDR), + .CHIP_SELS (CHIP_SELS) + ) epcq_controller_inst ( + .clk (clk ), + .reset_n (reset_n ), + .avl_csr_write (avl_csr_write ), + .avl_csr_read (avl_csr_read ), + .avl_csr_addr (avl_csr_addr ), + .avl_csr_wrdata (avl_csr_wrdata ), + .avl_csr_rddata (avl_csr_rddata ), + .avl_csr_rddata_valid (avl_csr_rddata_valid ), + .avl_csr_waitrequest (avl_csr_waitrequest ), + .avl_mem_write (avl_mem_write ), + .avl_mem_read (avl_mem_read ), + .avl_mem_addr (avl_mem_addr ), + .avl_mem_wrdata (avl_mem_wrdata ), + .avl_mem_burstcount (avl_mem_burstcount ), + .avl_mem_byteenable (avl_mem_byteenable ), + .avl_mem_rddata (avl_mem_rddata ), + .avl_mem_rddata_valid (avl_mem_rddata_valid ), + .avl_mem_waitrequest (avl_mem_waitrequest ), + .irq (irq ), +`ifdef DDASI_ON + .epcq_dataout (epcq_dataout ), + .epcq_dclk (epcq_dclk ), + .epcq_scein (epcq_scein ), + .epcq_sdoin (epcq_sdoin ), + .epcq_dataoe (epcq_dataoe ), + .ddasi_dataoe (ddasi_dataoe ), + .ddasi_dataout (ddasi_dataout ), + .ddasi_dclk (ddasi_dclk ), + .ddasi_scein (ddasi_scein ), + .ddasi_sdoin (ddasi_sdoin ), +`else + .epcq_dataout ({ASI_WIDTH{1'b0}} ), + .epcq_dclk ( ), + .epcq_scein ( ), + .epcq_sdoin ( ), + .epcq_dataoe ( ), + .ddasi_dataoe ({ASI_WIDTH{1'b0}} ), + .ddasi_dataout ( ), + .ddasi_dclk (1'b0 ), + .ddasi_scein ({CS_WIDTH{1'b0}} ), + .ddasi_sdoin ({ASI_WIDTH{1'b0}} ), +`endif + .asmi_busy (asmi_busy ), + .asmi_data_valid (asmi_data_valid ), + .asmi_dataout (asmi_dataout ), + .asmi_clkin (asmi_clkin ), + .asmi_reset (asmi_reset ), +`ifdef MULTICHIP + .asmi_sce (asmi_sce ), +`else + .asmi_sce ( ), +`endif + .asmi_addr (asmi_addr ), + .asmi_datain (asmi_datain ), + .asmi_fast_read (asmi_fast_read ), + .asmi_rden (asmi_rden ), + .asmi_shift_bytes (asmi_shift_bytes ), + .asmi_wren (asmi_wren ), + .asmi_write (asmi_write ), + .asmi_illegal_erase (asmi_illegal_erase ), + .asmi_illegal_write (asmi_illegal_write ), + .asmi_rdid_out (asmi_rdid_out ), + .asmi_status_out (asmi_status_out ), +`ifdef ENABLE_SID + .asmi_epcs_id (asmi_epcs_id ), + .asmi_read_sid (asmi_read_sid ), +`else + .asmi_epcs_id ({8{1'b0}} ), + .asmi_read_sid ( ), +`endif + .asmi_read_rdid (asmi_read_rdid ), + .asmi_read_status (asmi_read_status ), +`ifdef ENABLE_4BYTE_ADDR_CODE + .asmi_en4b_addr (asmi_en4b_addr ), +`else + .asmi_en4b_addr ( ), +`endif +`ifdef ENABLE_BULK_ERASE + .asmi_bulk_erase (asmi_bulk_erase ), +`else + .asmi_bulk_erase ( ), +`endif + .asmi_sector_erase (asmi_sector_erase ), + .asmi_sector_protect (asmi_sector_protect ) + ); + + altera_asmi_parallel asmi_parallel_inst ( + .busy (asmi_busy ), + .data_valid (asmi_data_valid ), + .dataout (asmi_dataout ), + .clkin (asmi_clkin ), + .reset (asmi_reset ), +`ifdef MULTICHIP + .sce (asmi_sce ), +`endif + .addr (asmi_addr ), + .datain (asmi_datain ), + .fast_read (asmi_fast_read ), + .rden (asmi_rden ), + .shift_bytes (asmi_shift_bytes ), + .wren (asmi_wren ), + .write (asmi_write ), + .illegal_erase (asmi_illegal_erase ), + .illegal_write (asmi_illegal_write ), + .rdid_out (asmi_rdid_out ), + .status_out (asmi_status_out ), + .read_dummyclk (1'b0), +`ifdef ENABLE_SID + .epcs_id (asmi_epcs_id ), + .read_sid (asmi_read_sid ), +`endif + .read_rdid (asmi_read_rdid ), + .read_status (asmi_read_status ), +`ifdef ENABLE_4BYTE_ADDR_CODE + .en4b_addr (asmi_en4b_addr ), +`endif +`ifdef ENABLE_BULK_ERASE + .bulk_erase (asmi_bulk_erase ), +`endif +`ifdef DDASI_ON + .asmi_dataoe (ddasi_dataoe ), + .asmi_dataout (ddasi_dataout ), + .asmi_dclk (ddasi_dclk ), + .asmi_scein (ddasi_scein ), + .asmi_sdoin (ddasi_sdoin ) +`endif + .sector_erase (asmi_sector_erase ), + .sector_protect (asmi_sector_protect ) + ); + +endmodule diff --git a/ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper_hw.tcl b/ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper_hw.tcl new file mode 100644 index 0000000..7b8a910 --- /dev/null +++ b/ip/altera_epcq_controller_mod/altera_epcq_controller_wrapper_hw.tcl @@ -0,0 +1,648 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +package require -exact qsys 14.1 +package require -exact altera_terp 1.0 + + +# +# module altera_trace_wrapper +# +set_module_property DESCRIPTION "This component is a serial flash controller which allows user to access Altera EPCQ devices" +set_module_property NAME altera_epcq_controller_mod +set_module_property VERSION 15.1 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property GROUP "Basic Functions/Configuration and Programming" +set_module_property AUTHOR "Altera Corporation" +set_module_property DISPLAY_NAME "Altera Serial Flash Controller" +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property HIDE_FROM_QUARTUS true +set_module_property EDITABLE true +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false +set_module_property ELABORATION_CALLBACK elaboration + +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH add_topwrapper_fileset_proc +set_fileset_property QUARTUS_SYNTH TOP_LEVEL altera_epcq_controller_wrapper +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false + +add_fileset SIM_VERILOG SIM_VERILOG add_topwrapper_fileset_proc +set_fileset_property SIM_VERILOG TOP_LEVEL altera_epcq_controller_wrapper +set_fileset_property SIM_VERILOG ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property SIM_VERILOG ENABLE_FILE_OVERWRITE_MODE true +# +# parameters +# +# +----------------------------------- +# | device family info +# +----------------------------------- +set all_supported_device_families_list {"Arria 10" "Cyclone V" "Arria V GZ" "Arria V" "Stratix V" "Stratix IV" \ + "Cyclone IV GX" "Cyclone IV E" "Cyclone III GL" "Arria II GZ" "Arria II GX"} + +proc check_device_ini {device_families_list} { + + set enable_max10 [get_quartus_ini enable_max10_active_serial ENABLED] + + if {$enable_max10 == 1} { + lappend device_families_list "MAX 10 FPGA" + } + return $device_families_list +} + +set device_list [check_device_ini $all_supported_device_families_list] +set_module_property SUPPORTED_DEVICE_FAMILIES $device_list + +add_parameter DEVICE_FAMILY STRING +set_parameter_property DEVICE_FAMILY SYSTEM_INFO {DEVICE_FAMILY} +set_parameter_property DEVICE_FAMILY VISIBLE false +set_parameter_property DEVICE_FAMILY HDL_PARAMETER true + +add_parameter ASI_WIDTH INTEGER 1 +set_parameter_property ASI_WIDTH DEFAULT_VALUE 1 +set_parameter_property ASI_WIDTH DISPLAY_NAME ASI_WIDTH +set_parameter_property ASI_WIDTH DERIVED true +set_parameter_property ASI_WIDTH TYPE INTEGER +set_parameter_property ASI_WIDTH VISIBLE false +set_parameter_property ASI_WIDTH UNITS None +set_parameter_property ASI_WIDTH ALLOWED_RANGES {1, 4} +set_parameter_property ASI_WIDTH HDL_PARAMETER true + +add_parameter CS_WIDTH INTEGER 1 +set_parameter_property CS_WIDTH DEFAULT_VALUE 1 +set_parameter_property CS_WIDTH DISPLAY_NAME CS_WIDTH +set_parameter_property CS_WIDTH DERIVED true +set_parameter_property CS_WIDTH TYPE INTEGER +set_parameter_property CS_WIDTH VISIBLE false +set_parameter_property CS_WIDTH UNITS None +set_parameter_property CS_WIDTH ALLOWED_RANGES {1, 3} +set_parameter_property CS_WIDTH HDL_PARAMETER true + +add_parameter ADDR_WIDTH INTEGER 19 +set_parameter_property ADDR_WIDTH DEFAULT_VALUE 19 +set_parameter_property ADDR_WIDTH DISPLAY_NAME ADDR_WIDTH +set_parameter_property ADDR_WIDTH DERIVED true +set_parameter_property ADDR_WIDTH TYPE INTEGER +set_parameter_property ADDR_WIDTH VISIBLE false +set_parameter_property ADDR_WIDTH UNITS None +# 16M-19bit, 32M-20bit, 64M-21bit, 128M-22bit, 256M-23bit, 512M-24bit, 1024M-25bit, 2048M-26bit... +set_parameter_property ADDR_WIDTH ALLOWED_RANGES {19, 20, 21, 22, 23, 24, 25, 26, 27, 28} +set_parameter_property ADDR_WIDTH HDL_PARAMETER true + +add_parameter ASMI_ADDR_WIDTH INTEGER 24 +set_parameter_property ASMI_ADDR_WIDTH DEFAULT_VALUE 24 +set_parameter_property ASMI_ADDR_WIDTH DISPLAY_NAME ASMI_ADDR_WIDTH +set_parameter_property ASMI_ADDR_WIDTH DERIVED true +set_parameter_property ASMI_ADDR_WIDTH TYPE INTEGER +set_parameter_property ASMI_ADDR_WIDTH VISIBLE false +set_parameter_property ASMI_ADDR_WIDTH UNITS None +set_parameter_property ASMI_ADDR_WIDTH ALLOWED_RANGES {24, 32} +set_parameter_property ASMI_ADDR_WIDTH HDL_PARAMETER true + +add_parameter ENABLE_4BYTE_ADDR INTEGER "0" +set_parameter_property ENABLE_4BYTE_ADDR DISPLAY_NAME "Enable 4-byte addressing mode" +set_parameter_property ENABLE_4BYTE_ADDR DESCRIPTION "Check to enable 4-byte addressing mode for device larger than 128Mbyte" +set_parameter_property ENABLE_4BYTE_ADDR AFFECTS_GENERATION true +set_parameter_property ENABLE_4BYTE_ADDR VISIBLE false +set_parameter_property ENABLE_4BYTE_ADDR HDL_PARAMETER true +set_parameter_property ENABLE_4BYTE_ADDR DERIVED true + +# +----------------------------------- + +# add system info parameter +add_parameter deviceFeaturesSystemInfo STRING "None" +set_parameter_property deviceFeaturesSystemInfo system_info "DEVICE_FEATURES" +set_parameter_property deviceFeaturesSystemInfo VISIBLE false + +add_parameter DDASI INTEGER "0" +set_parameter_property DDASI DISPLAY_NAME "Disable dedicated Active Serial interface" +set_parameter_property DDASI DESCRIPTION "Check to route ASMIBLOCK signals to top level of design" +set_parameter_property DDASI AFFECTS_GENERATION true +set_parameter_property DDASI VISIBLE false +set_parameter_property DDASI DERIVED false + +add_parameter clkFreq LONG +set_parameter_property clkFreq DEFAULT_VALUE {0} +set_parameter_property clkFreq DISPLAY_NAME {clkFreq} +set_parameter_property clkFreq VISIBLE {0} +set_parameter_property clkFreq AFFECTS_GENERATION {1} +set_parameter_property clkFreq HDL_PARAMETER {0} +set_parameter_property clkFreq SYSTEM_INFO {clock_rate clk} +set_parameter_property clkFreq SYSTEM_INFO_TYPE {CLOCK_RATE} +set_parameter_property clkFreq SYSTEM_INFO_ARG {clock_sink} + +# +# connection point clock_sink +# +add_interface clock_sink clock end +set_interface_property clock_sink clockRate 0 +set_interface_property clock_sink ENABLED true +set_interface_property clock_sink EXPORT_OF "" +set_interface_property clock_sink PORT_NAME_MAP "" +set_interface_property clock_sink CMSIS_SVD_VARIABLES "" +set_interface_property clock_sink SVD_ADDRESS_GROUP "" + +add_interface_port clock_sink clk clk Input 1 + + +# +# connection point reset +# +add_interface reset reset end +set_interface_property reset associatedClock clock_sink +set_interface_property reset synchronousEdges DEASSERT +set_interface_property reset ENABLED true +set_interface_property reset EXPORT_OF "" +set_interface_property reset PORT_NAME_MAP "" +set_interface_property reset CMSIS_SVD_VARIABLES "" +set_interface_property reset SVD_ADDRESS_GROUP "" + +add_interface_port reset reset_n reset_n Input 1 + + +# +# connection point avl_csr +# +add_interface avl_csr avalon end +set_interface_property avl_csr addressUnits WORDS +set_interface_property avl_csr associatedClock clock_sink +set_interface_property avl_csr associatedReset reset +set_interface_property avl_csr bitsPerSymbol 8 +set_interface_property avl_csr burstOnBurstBoundariesOnly false +set_interface_property avl_csr burstcountUnits WORDS +set_interface_property avl_csr explicitAddressSpan 0 +set_interface_property avl_csr holdTime 0 +set_interface_property avl_csr linewrapBursts false +set_interface_property avl_csr maximumPendingReadTransactions 1 +set_interface_property avl_csr maximumPendingWriteTransactions 0 +set_interface_property avl_csr readLatency 0 +set_interface_property avl_csr readWaitTime 0 +set_interface_property avl_csr setupTime 0 +set_interface_property avl_csr timingUnits Cycles +set_interface_property avl_csr writeWaitTime 0 +set_interface_property avl_csr ENABLED true +set_interface_property avl_csr EXPORT_OF "" +set_interface_property avl_csr PORT_NAME_MAP "" +set_interface_property avl_csr CMSIS_SVD_VARIABLES "" +set_interface_property avl_csr SVD_ADDRESS_GROUP "" + +add_interface_port avl_csr avl_csr_read read Input 1 +add_interface_port avl_csr avl_csr_waitrequest waitrequest Output 1 +add_interface_port avl_csr avl_csr_write write Input 1 +add_interface_port avl_csr avl_csr_addr address Input 3 +add_interface_port avl_csr avl_csr_wrdata writedata Input 32 +add_interface_port avl_csr avl_csr_rddata readdata Output 32 +add_interface_port avl_csr avl_csr_rddata_valid readdatavalid Output 1 + +# +# connection point avl_mem +# +add_interface avl_mem avalon end +set_interface_property avl_mem addressUnits WORDS +set_interface_property avl_mem associatedClock clock_sink +set_interface_property avl_mem associatedReset reset +set_interface_property avl_mem bitsPerSymbol 8 +set_interface_property avl_mem burstOnBurstBoundariesOnly false +set_interface_property avl_mem burstcountUnits WORDS +set_interface_property avl_mem explicitAddressSpan 0 +set_interface_property avl_mem holdTime 0 +set_interface_property avl_mem linewrapBursts true +set_interface_property avl_mem maximumPendingReadTransactions 1 +set_interface_property avl_mem maximumPendingWriteTransactions 0 +set_interface_property avl_mem constantBurstBehavior true +set_interface_property avl_mem readLatency 0 +set_interface_property avl_mem readWaitTime 0 +set_interface_property avl_mem setupTime 0 +set_interface_property avl_mem timingUnits Cycles +set_interface_property avl_mem writeWaitTime 0 +set_interface_property avl_mem ENABLED true +set_interface_property avl_mem EXPORT_OF "" +set_interface_property avl_mem PORT_NAME_MAP "" +set_interface_property avl_mem CMSIS_SVD_VARIABLES "" +set_interface_property avl_mem SVD_ADDRESS_GROUP "" + +add_interface_port avl_mem avl_mem_write write Input 1 +add_interface_port avl_mem avl_mem_burstcount burstcount Input 7 +add_interface_port avl_mem avl_mem_waitrequest waitrequest Output 1 +add_interface_port avl_mem avl_mem_read read Input 1 +add_interface_port avl_mem avl_mem_addr address Input ADDR_WIDTH +add_interface_port avl_mem avl_mem_wrdata writedata Input 32 +add_interface_port avl_mem avl_mem_rddata readdata Output 32 +add_interface_port avl_mem avl_mem_rddata_valid readdatavalid Output 1 +add_interface_port avl_mem avl_mem_byteenable byteenable Input 4 + +# +# connection point interrupt_sender +# +add_interface interrupt_sender interrupt end +set_interface_property interrupt_sender associatedAddressablePoint avl_csr +set_interface_property interrupt_sender associatedClock clock_sink +set_interface_property interrupt_sender associatedReset reset +set_interface_property interrupt_sender bridgedReceiverOffset "" +set_interface_property interrupt_sender bridgesToReceiver "" +set_interface_property interrupt_sender ENABLED true +set_interface_property interrupt_sender EXPORT_OF "" +set_interface_property interrupt_sender PORT_NAME_MAP "" +set_interface_property interrupt_sender CMSIS_SVD_VARIABLES "" +set_interface_property interrupt_sender SVD_ADDRESS_GROUP "" + +add_interface_port interrupt_sender irq irq Output 1 + +proc proc_get_derive_addr_width {flash_type} { + switch $flash_type { + "EPCS16" - "EPCQ16" { + return 19 + } + "EPCS64" - "EPCQ64" { + return 21 + } + "EPCS128" - "EPCQ128" { + return 22 + } + "EPCQ32" { + return 20 + } + "EPCQ256" - "EPCQL256" { + return 23 + } + "EPCQ512" - "EPCQL512" { + return 24 + } + "EPCQL1024" { + return 25 + } + default { + # Should never enter this function + send_message error "$flash_type is not a valid flash type" + } + + } +} + +set all_supported_SPI_list {"EPCS16" "EPCS64" "EPCS128" "EPCQ16" "EPCQ32" "EPCQ64" "EPCQ128" "EPCQ256" \ + "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024"} + +# SPI device selection +add_parameter FLASH_TYPE STRING "EPCQ16" +set_parameter_property FLASH_TYPE DISPLAY_NAME "Configuration device type" +set_parameter_property FLASH_TYPE ALLOWED_RANGES $all_supported_SPI_list +set_parameter_property FLASH_TYPE DESCRIPTION "Select targeted EPCS/EPCQ devices" +set_parameter_property FLASH_TYPE AFFECTS_GENERATION true +set_parameter_property FLASH_TYPE VISIBLE true +set_parameter_property FLASH_TYPE DERIVED false + +add_parameter IO_MODE STRING "STANDARD" +set_parameter_property IO_MODE DISPLAY_NAME "Choose I/O mode" +set_parameter_property IO_MODE ALLOWED_RANGES {"STANDARD" "QUAD"} +set_parameter_property IO_MODE DESCRIPTION "Select extended data width when Fast Read operation is enabled" + +add_parameter CHIP_SELS INTEGER "1" +set_parameter_property CHIP_SELS DISPLAY_NAME "Number of Chip Selects used" +set_parameter_property CHIP_SELS ALLOWED_RANGES {1 2 3} +set_parameter_property CHIP_SELS DESCRIPTION "Number of EPCQ(L) devices that are attached and need a CHIPSEL" +set_parameter_property CHIP_SELS HDL_PARAMETER true +set_parameter_property CHIP_SELS AFFECTS_GENERATION true +# +# Add instance +# +proc add_topwrapper_fileset_proc {altera_epcq_controller} { + # QSPI that supported for 4-byte addressing - en4b_addr, ex4b_addr + set supported_4byte_addr {"EPCQ256" "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024" "N25Q512"} + set DDASI [ get_parameter_value DDASI ] + set DEVICE_FAMILY [ get_parameter_value DEVICE_FAMILY ] + set FLASH_TYPE [ get_parameter_value FLASH_TYPE ] + set ADDR_WIDTH [ get_parameter_value ADDR_WIDTH ] + set is_4byte_addr_support "false" + + # check whether devices supporting multiple flash - only for Arria 10 + if {[check_device_family_equivalence $DEVICE_FAMILY "Arria 10"]} { + set MULTICHIP 1 + } else { + set MULTICHIP 0 + } + + if { $DDASI eq "1" } { + set DDASI_ON 1 + } else { + set DDASI_ON 0 + } + + if { $FLASH_TYPE eq "EPCS16" || $FLASH_TYPE eq "EPCS64" } { + set ENABLE_SID 1 + } else { + set ENABLE_SID 0 + } + + if { $FLASH_TYPE eq "EPCQL512" || $FLASH_TYPE eq "EPCQL1024" } { + set ENABLE_BULK_ERASE 0 + } else { + set ENABLE_BULK_ERASE 1 + } + + # check whether SPI device support 4-byte addressing + foreach re_spi_1 $supported_4byte_addr { + if {$re_spi_1 eq $FLASH_TYPE} { + set is_4byte_addr_support "true" + break; + } + } + + if {$is_4byte_addr_support eq "true"} { + set ENABLE_4BYTE_ADDR_CODE 1 + } else { + set ENABLE_4BYTE_ADDR_CODE 0 + } + + # --------------------------------- + # Terp for top level wrapper + # --------------------------------- + #Do Terp + set template_file [ file join "./" "altera_epcq_controller_wrapper.sv.terp" ] + set template [ read [ open $template_file r ] ] + + if {$DDASI_ON} { + set params(DDASI_ON) "`define DDASI_ON" + } else { + set params(DDASI_ON) "" + } + + if {$MULTICHIP} { + set params(MULTICHIP) "`define MULTICHIP" + } else { + set params(MULTICHIP) "" + } + + if {$ENABLE_SID} { + set params(SID_EN) "`define ENABLE_SID" + } else { + set params(SID_EN) "" + } + + if {$ENABLE_BULK_ERASE} { + set params(BULK_ERASE_EN) "`define ENABLE_BULK_ERASE" + } else { + set params(BULK_ERASE_EN) "" + } + + if {$ENABLE_4BYTE_ADDR_CODE} { + set params(4BYTE_ADDR_EN) "`define ENABLE_4BYTE_ADDR_CODE" + } else { + set params(4BYTE_ADDR_EN) "" + } + + set result [ altera_terp $template params ] + + #Add top wrapper file + add_fileset_file ./altera_epcq_controller_wrapper.sv SYSTEM_VERILOG TEXT $result +} + +# This proc is called by elaboration proc to set embeddedsw C Macros assignments +# used by downstream tools +proc set_cmacros {is_qspi flash_type} { + if {$is_qspi eq "true"} { + set_module_assignment embeddedsw.CMacro.IS_EPCS 0 + } else { + set_module_assignment embeddedsw.CMacro.IS_EPCS 1 + } + + #string name of flash + set_module_assignment embeddedsw.CMacro.FLASH_TYPE $flash_type + + #page size in bytes + set_module_assignment embeddedsw.CMacro.PAGE_SIZE 256 + + #sector and subsector size in bytes + set_module_assignment embeddedsw.CMacro.SUBSECTOR_SIZE 4096 + set_module_assignment embeddedsw.CMacro.SECTOR_SIZE 65536 + + #set number of sectors + switch $flash_type { + "EPCS16" - "EPCQ16" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 32 + } + "EPCQ32" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 64 + } + "EPCS64" - "EPCQ64" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 128 + } + "EPCS128" - "EPCQ128" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 256 + } + "EPCQ256" - "EPCQL256" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 512 + } + "EPCQ512" - "EPCQL512" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 1024 + } + "EPCQL1024" { + set_module_assignment embeddedsw.CMacro.NUMBER_OF_SECTORS 2048 + } + default { + # Should never enter this function + send_message error "$flash_type is not a valid flash type" + } + } +} + +proc elaboration {} { + # QSPI that supported for 4-byte addressing - en4b_addr, ex4b_addr + set supported_4byte_addr {"EPCQ256" "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024" "N25Q512"} + set DDASI_ON [ get_parameter_value DDASI ] + set FLASH_TYPE [ get_parameter_value FLASH_TYPE ] + set IO_MODE [ get_parameter_value IO_MODE ] + set DEVICE_FAMILY [ get_parameter_value DEVICE_FAMILY ] + set ASI_WIDTH [ get_parameter_value ASI_WIDTH ] + set CS_WIDTH [ get_parameter_value CS_WIDTH ] + set ASMI_ADDR_WIDTH [ get_parameter_value ASMI_ADDR_WIDTH ] + set CHIP_SELS [ get_parameter_value CHIP_SELS] + set temp_addr_width [ proc_get_derive_addr_width [ get_parameter_value FLASH_TYPE ] ] + set clkFreq [ get_parameter_value clkFreq ] + set is_4byte_addr_support "false" + set is_qspi "false" + + # we're not using slow and expensive EPCS flash, thus higher frequency allowed + if { $clkFreq > 50000000 } { + send_message error "The maximum input clock frequency for Altera Serial Flash controller is 25Mhz." + } + + # check whether SPI device support 4-byte addressing + foreach re_spi_1 $supported_4byte_addr { + if {$re_spi_1 eq $FLASH_TYPE} { + set is_4byte_addr_support "true" + break; + } + } + + if {$is_4byte_addr_support eq "true"} { + set_parameter_value ENABLE_4BYTE_ADDR "1" + set_parameter_value ASMI_ADDR_WIDTH 32 + } else { + set_parameter_value ENABLE_4BYTE_ADDR "0" + set_parameter_value ASMI_ADDR_WIDTH 24 + } + + # check whether devices supporting multiple flash - only for Arria 10 + if {[check_device_family_equivalence $DEVICE_FAMILY "Arria 10"]} { + set is_multi_flash_support "true" + if {$CHIP_SELS eq 3 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 2]} + if {$CHIP_SELS eq 2 } {set_parameter_value ADDR_WIDTH [ expr $temp_addr_width + 1]} + if {$CHIP_SELS eq 1 } {set_parameter_value ADDR_WIDTH $temp_addr_width } + } else { + set is_multi_flash_support "false" + set_parameter_value ADDR_WIDTH $temp_addr_width + } + + + set_instance_parameter_value altera_epcq_controller_core DDASI $DDASI_ON + set_instance_parameter_value altera_epcq_controller_core FLASH_TYPE $FLASH_TYPE + set_instance_parameter_value altera_epcq_controller_core IO_MODE $IO_MODE + set_instance_parameter_value altera_epcq_controller_core ASI_WIDTH $ASI_WIDTH + set_instance_parameter_value altera_epcq_controller_core CS_WIDTH $CS_WIDTH + set_instance_parameter_value altera_epcq_controller_core CHIP_SELS $CHIP_SELS + set_instance_parameter_value altera_epcq_controller_core ASMI_ADDR_WIDTH [ get_parameter_value ASMI_ADDR_WIDTH ] + set_instance_parameter_value altera_epcq_controller_core ADDR_WIDTH [ get_parameter_value ADDR_WIDTH ] + set_instance_parameter_value altera_epcq_controller_core ENABLE_4BYTE_ADDR [ get_parameter_value ENABLE_4BYTE_ADDR ] + + set QSPI_list {"EPCQ16" "EPCQ32" "EPCQ64" "EPCQ128" "EPCQ256" "EPCQ512" "EPCQL256" "EPCQL512" "EPCQL1024" \ + "N25Q512" "S25FL127S"} + + # devices that supported QSPI - Quad/Dual data width, asmi_dataout, asmi_sdoin, asmi_dataoe + set supported_QSPI_devices_list {"Arria 10" "Cyclone V" "Arria V GZ" "Arria V" "Stratix V"} + + # devices that supported simulation + set supported_sim_devices_list {"Arria 10" "Cyclone V" "Arria V GZ" "Arria V" "Stratix V" "MAX 10 FPGA"} + + # check whether is QSPI devices + foreach re_spi_0 $QSPI_list { + if {$re_spi_0 eq $FLASH_TYPE} { + set is_qspi "true" + break; + } + } + + if {[check_device_family_equivalence $DEVICE_FAMILY $supported_QSPI_devices_list]} { + set is_qspi_devices_list "true" + } else { + set is_qspi_devices_list "false" + } + + if {[check_device_family_equivalence $DEVICE_FAMILY $supported_sim_devices_list]} { + set is_sim_devices_list "true" + } else { + set is_sim_devices_list "false" + } + + if {$is_qspi_devices_list eq "true" && $is_qspi eq "true"} { + set_parameter_property IO_MODE ENABLED true + set_instance_parameter_value altera_asmi_parallel DATA_WIDTH $IO_MODE + set_parameter_value ASI_WIDTH 4 + } else { + set_parameter_property IO_MODE ENABLED false + set_parameter_value ASI_WIDTH 1 + } + + if { $FLASH_TYPE eq "EPCQL512" || $FLASH_TYPE eq "EPCQL1024" } { + set_instance_parameter_value altera_asmi_parallel gui_bulk_erase false + set ENABLE_BULK_ERASE 0 + } else { + set_instance_parameter_value altera_asmi_parallel gui_bulk_erase true + set ENABLE_BULK_ERASE 1 + } + + if { $is_multi_flash_support eq "true"} { + set_parameter_value CS_WIDTH 3 + set_parameter_property CHIP_SELS ENABLED true + } else { + set_parameter_value CS_WIDTH 1 + set_parameter_property CHIP_SELS ENABLED false + } + + set_instance_parameter_value altera_asmi_parallel EPCS_TYPE $FLASH_TYPE + set_instance_parameter_value altera_asmi_parallel gui_fast_read true + set_instance_parameter_value altera_asmi_parallel gui_page_write true + + if { $FLASH_TYPE eq "EPCS16" || $FLASH_TYPE eq "EPCS64" } { + set_instance_parameter_value altera_asmi_parallel gui_read_sid true + } else { + set_instance_parameter_value altera_asmi_parallel gui_read_sid false + } + + set_instance_parameter_value altera_asmi_parallel gui_read_rdid true + set_instance_parameter_value altera_asmi_parallel gui_read_status true + set_instance_parameter_value altera_asmi_parallel gui_sector_erase true + set_instance_parameter_value altera_asmi_parallel gui_sector_protect true + set_instance_parameter_value altera_asmi_parallel gui_wren true + set_instance_parameter_value altera_asmi_parallel gui_write true + set_instance_parameter_value altera_asmi_parallel gui_read_dummyclk true + set_instance_parameter_value altera_asmi_parallel PAGE_SIZE 256 + set_instance_parameter_value altera_asmi_parallel gui_use_asmiblock $DDASI_ON + + if {$is_sim_devices_list eq "true"} { + set_instance_parameter_value altera_asmi_parallel ENABLE_SIM true + } else { + set_instance_parameter_value altera_asmi_parallel ENABLE_SIM false + } + + set_cmacros $is_qspi $FLASH_TYPE +} + +# add ASMI PARALLEL +add_hdl_instance altera_asmi_parallel altera_asmi_parallel + +# add EPCQ CONTROLLER +add_hdl_instance altera_epcq_controller_core altera_epcq_controller_core + +# +------------------------------------- +# | Add settings needed by Nios tools +# +------------------------------------- +# Tells us component is a flash +set_module_assignment embeddedsw.memoryInfo.IS_FLASH 1 + +# interface assignments for embedded software +set_interface_assignment avl_mem embeddedsw.configuration.isFlash 1 +set_interface_assignment avl_mem embeddedsw.configuration.isMemoryDevice 1 +set_interface_assignment avl_mem embeddedsw.configuration.isNonVolatileStorage 1 +set_interface_assignment avl_mem embeddedsw.configuration.isPrintableDevice 0 + +# These assignments tells tools to create byte-addressed .hex files only +set_module_assignment embeddedsw.memoryInfo.GENERATE_HEX 1 +set_module_assignment embeddedsw.memoryInfo.USE_BYTE_ADDRESSING_FOR_HEX 1 +set_module_assignment embeddedsw.memoryInfo.GENERATE_DAT_SYM 0 +set_module_assignment embeddedsw.memoryInfo.GENERATE_FLASH 0 + +# Width of memory +set_module_assignment embeddedsw.memoryInfo.MEM_INIT_DATA_WIDTH 32 + +# Output directories for programming files +#set_module_assignment embeddedsw.memoryInfo.DAT_SYM_INSTALL_DIR {SIM_DIR} +#set_module_assignment embeddedsw.memoryInfo.FLASH_INSTALL_DIR {APP_DIR} +set_module_assignment embeddedsw.memoryInfo.HEX_INSTALL_DIR {QPF_DIR} + +# Module assignments related to names of simulation files +#set_module_assignment postgeneration.simulation.init_file.param_name {INIT_FILENAME} +#set_module_assignment postgeneration.simulation.init_file.type {MEM_INIT} + +# +------------------------------------- +# | Add settings needed by DTG tools +# +------------------------------------- +# add device tree properties +set_module_assignment embeddedsw.dts.vendor "altr" +set_module_assignment embeddedsw.dts.name "epcq" +set_module_assignment embeddedsw.dts.group "epcq" +set_module_assignment embeddedsw.dts.compatible "altr,epcq-1.0" + +## Add documentation links for user guide and/or release notes +add_documentation_link "User Guide" https://documentation.altera.com/#/link/sfo1400787952932/iga1431459459085 +add_documentation_link "Release Notes" https://documentation.altera.com/#/link/hco1421698042087/hco1421697689300 diff --git a/ip/altera_epcq_controller_mod/inc/altera_epcq_controller_mod_regs.h b/ip/altera_epcq_controller_mod/inc/altera_epcq_controller_mod_regs.h new file mode 100644 index 0000000..3d36697 --- /dev/null +++ b/ip/altera_epcq_controller_mod/inc/altera_epcq_controller_mod_regs.h @@ -0,0 +1,260 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2014 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALTERA_EPCQ_CONTROLLER_REGS_H__ +#define __ALTERA_EPCQ_CONTROLLER_REGS_H__ + +#include + +/* + * EPCQ_RD_STATUS register offset + * + * The EPCQ_RD_STATUS register contains information from the read status + * register operation. A full description of the register can be found in the + * data sheet, + * + */ +#define ALTERA_EPCQ_CONTROLLER_STATUS_REG (0x0) + +/* + * EPCQ_RD_STATUS register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_STATUS(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_STATUS(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_STATUS(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG, data) + +/* + * EPCQ_RD_STATUS register description macros + */ + +/** Write in progress bit */ +#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_AVAILABLE (0x00000000) +#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY (0x00000001) +/** When to time out a poll of the write in progress bit */ +/* 0.7 sec time out */ +#define ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE 700000 + +/* + * EPCQ_RD_SID register offset + * + * The EPCQ_RD_SID register contains the information from the read silicon ID + * operation and can be used to determine what type of EPCS device we have. + * Only support in EPCS16 and EPCS64. + * + * This register is valid only if the device is an EPCS. + * + */ +#define ALTERA_EPCQ_CONTROLLER_SID_REG (0x4) + +/* + * EPCQ_RD_SID register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_SID(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_SID_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_SID(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_SID_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_SID(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_SID_REG, data) + +/* + * EPCQ_RD_SID register description macros + * + * Specific device values obtained from Table 14 of: + * "Serial Configuration (EPCS) Devices Datasheet" + */ +#define ALTERA_EPCQ_CONTROLLER_SID_MASK (0x000000FF) +#define ALTERA_EPCQ_CONTROLLER_SID_EPCS16 (0x00000014) +#define ALTERA_EPCQ_CONTROLLER_SID_EPCS64 (0x00000016) +#define ALTERA_EPCQ_CONTROLLER_SID_EPCS128 (0x00000018) + +/* + * EPCQ_RD_RDID register offset + * + * The EPCQ_RD_RDID register contains the information from the read memory + * capacity operation and can be used to determine what type of EPCQ device + * we have. + * + * This register is only valid if the device is an EPCQ. + * + */ +#define ALTERA_EPCQ_CONTROLLER_RDID_REG (0x8) + +/* + * EPCQ_RD_RDID register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_RDID(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_RDID_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_RDID(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_RDID_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_RDID(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_RDID_REG, data) + +/* + * EPCQ_RD_RDID register description macros + * + * Specific device values obtained from Table 28 of: + * "Quad-Serial Configuration (EPCQ (www.altera.com/literature/hb/cfg/cfg_cf52012.pdf)) + * Devices Datasheet" + */ +#define ALTERA_EPCQ_CONTROLLER_RDID_MASK (0x000000FF) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16 (0x00000015) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32 (0x00000016) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64 (0x00000017) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128 (0x00000018) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256 (0x00000019) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512 (0x00000020) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024 (0x00000021) + +/* + * EPCQ_MEM_OP register offset + * + * The EPCQ_MEM_OP register is used to do memory protect and erase operations + * + */ +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_REG (0xC) + +/* + * EPCQ_MEM_OP register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_MEM_OP(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_MEM_OP(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG, data) + +/* + * EPCQ_MEM_OP register description macros + */ +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_CMD_MASK (0x00000003) +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_BULK_ERASE_CMD (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD (0x00000002) +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD (0x00000003) + +/** see datasheet for sector values */ +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK (0x00FFFF00) + +/* + * EPCQ_ISR register offset + * + * The EPCQ_ISR register is used to determine whether an invalid write or erase + * operation triggered an interrupt + * + */ +#define ALTERA_EPCQ_CONTROLLER_ISR_REG (0x10) + +/* + * EPCQ_ISR register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_ISR(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_ISR_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_ISR(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_ISR_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_ISR(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_ISR_REG, data) + +/* + * EPCQ_ISR register description macros + */ +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE (0x00000001) + +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK (0x00000002) +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE (0x00000002) + + +/* + * EPCQ_IMR register offset + * + * The EPCQ_IMR register is used to mask the invalid erase or the invalid write + * interrupts. + * + */ +#define ALTERA_EPCQ_CONTROLLER_IMR_REG (0x14) + +/* + * EPCQ_IMR register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_IMR(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_IMR_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_IMR(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_IMR_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_IMR(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_IMR_REG, data) + +/* + * EPCQ_IMR register description macros + */ +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_ERASE_MASK (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_ERASE_ENABLED (0x00000001) + +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_WRITE_MASK (0x00000002) +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_WRITE_ENABLED (0x00000002) + +/* + * EPCQ_CHIP_SELECT register offset + * + * The EPCQ_CHIP_SELECT register is used to issue chip select + */ +#define ALTERA_EPCQ_CHIP_SELECT_REG (0x18) + +/* + * EPCQ_CHIP_SELECT register access macros + */ +#define IOADDR_ALTERA_EPCQ_CHIP_SELECT(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CHIP_SELECT_REG) + +#define IOWR_ALTERA_EPCQ_CHIP_SELECT(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CHIP_SELECT_REG, data) + +/* + * EPCQ_CHIP_SELECT register description macros + */ +#define ALTERA_EPCQ_CHIP1_SELECT (0x00000001) +#define ALTERA_EPCQ_CHIP2_SELECT (0x00000002) +#define ALTERA_EPCQ_CHIP3_SELECT (0x00000003) + +#endif /* __ALTERA_EPCQ_CONTROLLER_REGS_H__ */ diff --git a/ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys.v b/ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys.v new file mode 100644 index 0000000..16d875e --- /dev/null +++ b/ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys.v @@ -0,0 +1,56 @@ +// (C) 2001-2015 Altera Corporation. All rights reserved. +// Your use of Altera Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Altera Program License Subscription +// Agreement, Altera MegaCore Function License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Altera and sold by +// Altera or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +//Legal Notice: (C)2010 Altera Corporation. All rights reserved. Your +//use of Altera Corporation's design tools, logic functions and other +//software and tools, and its AMPP partner logic functions, and any +//output files any of the foregoing (including device programming or +//simulation files), and any associated documentation or information are +//expressly subject to the terms and conditions of the Altera Program +//License Subscription Agreement or other applicable license agreement, +//including, without limitation, that your use is for the sole purpose +//of programming logic devices manufactured by Altera and sold by Altera +//or its authorized distributors. Please refer to the applicable +//agreement for further details. + +// synthesis translate_off +`timescale 1ns / 1ps +// synthesis translate_on + +// turn off superfluous verilog processor warnings +// altera message_level Level1 +// altera message_off 10034 10035 10036 10037 10230 10240 10030 + +module endianconverter_qsys ( + // inputs: + dataa, + datab, + + // outputs: + result + ) +; + + output [ 31: 0] result; + input [ 31: 0] dataa; + input [ 31: 0] datab; + + wire [ 31: 0] result; + //s1, which is an e_custom_instruction_slave + assign result[7 : 0] = dataa[31 : 24]; + assign result[15 : 8] = dataa[23 : 16]; + assign result[23 : 16] = dataa[15 : 8]; + assign result[31 : 24] = dataa[7 : 0]; + +endmodule + diff --git a/ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys_hw.tcl b/ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys_hw.tcl new file mode 100644 index 0000000..76d9685 --- /dev/null +++ b/ip/altera_nios_custom_instr_endianconverter_qsys/endianconverter_qsys_hw.tcl @@ -0,0 +1,84 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# TCL File Generated by Component Editor 10.1 +# Tue Aug 17 15:04:48 MYT 2010 +# DO NOT MODIFY + + +# +----------------------------------- +# | +# | +# | ./converter_0.v syn, sim +# | +# +----------------------------------- + +# +----------------------------------- +# | request TCL package from ACDS 10.1 +# | +package require -exact sopc 10.1 +# | +# +----------------------------------- + +# +----------------------------------- +# | module altera_nios_custom_instr_endian_converter +# | +set_module_property NAME altera_nios_custom_instr_endianconverter +set_module_property VERSION "__VERSION_SHORT__" +set_module_property INTERNAL false +set_module_property GROUP "Custom Instruction Modules" +set_module_property AUTHOR "Altera Corporation" +set_module_property DISPLAY_NAME "Endian Converter" +set_module_property HIDE_FROM_SOPC true +set_module_property TOP_LEVEL_HDL_FILE endianconverter_qsys.v +set_module_property TOP_LEVEL_HDL_MODULE endianconverter_qsys +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property SIMULATION_MODEL_IN_VHDL true +set_module_property EDITABLE false +set_module_property ANALYZE_HDL FALSE +# | +# +----------------------------------- + +# +----------------------------------- +# | files +# | +add_file endianconverter_qsys.v {SYNTHESIS SIMULATION} +# | +# +----------------------------------- + +# +----------------------------------- +# | parameters +# | +# | +# +----------------------------------- + +# +----------------------------------- +# | display items +# | +# | +# +----------------------------------- + +# +----------------------------------- +# | connection point s1 +# | +add_interface s1 nios_custom_instruction end +set_interface_property s1 clockCycle 1 +set_interface_property s1 operands 1 + +set_interface_property s1 ENABLED true + +add_interface_port s1 dataa dataa Input 32 +add_interface_port s1 datab datab Input 32 +add_interface_port s1 result result Output 32 +# | +# +----------------------------------- diff --git a/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl b/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl new file mode 100644 index 0000000..c772941 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_hw.tcl @@ -0,0 +1,159 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# TCL File Generated by Component Editor 8.0 +# Mon Dec 22 17:22:07 EST 2008 +# DO NOT MODIFY + +set aup_version 15.1 + + + +# +----------------------------------- +# | +# | Altera_UP_SD_Card_Avalon_Interface "Altera_UP_SD_Card_Avalon_Interface" v1.0 +# | null 2008.12.22.17:22:07 +# | A module that allows communication with an SD Card +# | +# | ./hdl/Altera_UP_SD_Card_Avalon_Interface.vhd syn +# | ./hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd syn +# | ./hdl/Altera_UP_SD_Card_Buffer.vhd syn +# | ./hdl/Altera_UP_SD_Card_Clock.vhd syn +# | ./hdl/Altera_UP_SD_Card_Control_FSM.vhd syn +# | ./hdl/Altera_UP_SD_Card_Interface.vhd syn +# | ./hdl/Altera_UP_SD_Card_Memory_Block.qip syn +# | ./hdl/Altera_UP_SD_Card_Response_Receiver.vhd syn +# | ./hdl/Altera_UP_SD_CRC16_Generator.vhd syn +# | ./hdl/Altera_UP_SD_CRC7_Generator.vhd syn +# | ./hdl/Altera_UP_SD_Signal_Trigger.vhd syn +# | +# +----------------------------------- + + +# +----------------------------------- +# | module Altera_UP_SD_Card_Avalon_Interface +# | +set_module_property DESCRIPTION "A module that allows communication with an SD Card" +set_module_property NAME Altera_UP_SD_Card_Avalon_Interface_mod +set_module_property VERSION $aup_version +set_module_property GROUP "Memory" +set_module_property DISPLAY_NAME "SD Card Interface" +set_module_property DATASHEET_URL "[pwd]/doc/SD_Card_Interface_for_SoPC_Builder.pdf" +set_module_property LIBRARIES {ieee.std_logic_1164.all ieee.std_logic_arith.all ieee.std_logic_unsigned.all std.standard.all} +set_module_property TOP_LEVEL_HDL_FILE "hdl/Altera_UP_SD_Card_Avalon_Interface.vhd" +set_module_property TOP_LEVEL_HDL_MODULE Altera_UP_SD_Card_Avalon_Interface +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE false +#set_module_property ANALYZE_HDL false +set_module_property SIMULATION_MODEL_IN_VERILOG false +set_module_property SIMULATION_MODEL_IN_VHDL false +set_module_property SIMULATION_MODEL_HAS_TULIPS false +set_module_property SIMULATION_MODEL_IS_OBFUSCATED false +# | +# +----------------------------------- + +# +----------------------------------- +# | files +# | +add_file hdl/Altera_UP_SD_Card_Avalon_Interface.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_Buffer.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_Clock.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_Control_FSM.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_Interface.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_Response_Receiver.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_CRC16_Generator.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_CRC7_Generator.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Signal_Trigger.vhd {SYNTHESIS} +add_file hdl/Altera_UP_SD_Card_Memory_Block.vhd {SYNTHESIS} +# | +# +----------------------------------- + +# +----------------------------------- +# | parameters +# | +# | +# +----------------------------------- + +# +----------------------------------- +# | connection point avalon_sdcard_slave +# | +add_interface avalon_sdcard_slave avalon end +set_interface_property avalon_sdcard_slave holdTime 0 +set_interface_property avalon_sdcard_slave linewrapBursts false +set_interface_property avalon_sdcard_slave minimumUninterruptedRunLength 1 +set_interface_property avalon_sdcard_slave bridgesToMaster "" +set_interface_property avalon_sdcard_slave isMemoryDevice false +set_interface_property avalon_sdcard_slave burstOnBurstBoundariesOnly false +set_interface_property avalon_sdcard_slave addressSpan 1024 +set_interface_property avalon_sdcard_slave timingUnits Cycles +set_interface_property avalon_sdcard_slave setupTime 0 +set_interface_property avalon_sdcard_slave writeWaitTime 0 +set_interface_property avalon_sdcard_slave isNonVolatileStorage false +set_interface_property avalon_sdcard_slave addressAlignment DYNAMIC +set_interface_property avalon_sdcard_slave maximumPendingReadTransactions 0 +set_interface_property avalon_sdcard_slave readWaitTime 1 +set_interface_property avalon_sdcard_slave readLatency 0 +set_interface_property avalon_sdcard_slave printableDevice false + +set_interface_property avalon_sdcard_slave associatedClock clk +set_interface_property avalon_sdcard_slave associatedReset reset + +add_interface_port avalon_sdcard_slave i_avalon_chip_select chipselect Input 1 +add_interface_port avalon_sdcard_slave i_avalon_address address Input 8 +add_interface_port avalon_sdcard_slave i_avalon_read read Input 1 +add_interface_port avalon_sdcard_slave i_avalon_write write Input 1 +add_interface_port avalon_sdcard_slave i_avalon_byteenable byteenable Input 4 +add_interface_port avalon_sdcard_slave i_avalon_writedata writedata Input 32 +add_interface_port avalon_sdcard_slave o_avalon_readdata readdata Output 32 +add_interface_port avalon_sdcard_slave o_avalon_waitrequest waitrequest Output 1 +# | +# +----------------------------------- + +# +----------------------------------- +# | connection point clk +# | +add_interface clk clock end +set_interface_property clk enabled true + +add_interface_port clk i_clock clk Input 1 +# | +# +----------------------------------- + +# +----------------------------------- +# | connection point reset +# | +add_interface reset reset end +set_interface_property reset associatedClock clk +set_interface_property reset enabled true +set_interface_property reset synchronousEdges DEASSERT + +add_interface_port reset i_reset_n reset_n Input 1 +# | +# +----------------------------------- + +# +----------------------------------- +# | connection point conduit_end +# | +add_interface conduit_end conduit end + +add_interface_port conduit_end b_SD_cmd export Bidir 1 +add_interface_port conduit_end b_SD_dat export Bidir 1 +add_interface_port conduit_end b_SD_dat3 export Bidir 1 +add_interface_port conduit_end o_SD_clock export Output 1 +# | +# +----------------------------------- + +## Add documentation links for user guide and/or release notes +add_documentation_link "User Guide" file:///ip/altera/university_program/memory/altera_up_sd_card_avalon_interface/doc/SD_Card_Interface_for_SoPC_Builder.pdf +add_documentation_link "Release Notes" https://documentation.altera.com/#/link/hco1421698042087/hco1421698013408 diff --git a/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl b/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl new file mode 100644 index 0000000..9cc0821 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/Altera_UP_SD_Card_Avalon_Interface_sw.tcl @@ -0,0 +1,56 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# TCL File Generated by Altera University Program +# DO NOT MODIFY + +set aup_version 15.1 + +# Create a new driver - this name must be different than the +# hardware component name +create_driver Altera_UP_SD_Card_Avalon_Interface_mod_driver + +# Associate it with some hardware +set_sw_property hw_class_name Altera_UP_SD_Card_Avalon_Interface_mod + +# The version of this driver +set_sw_property version $aup_version + +# This driver is proclaimed to be compatible with 'component' +# as old as version "1.0". The component hardware version is set in the +# _hw.tcl file - If the hardware component version number is not equal +# or greater than the min_compatable_hw_version number, the driver +# source files will not be copied over to the BSP driver directory +set_sw_property min_compatible_hw_version 15.1 + +# Initialize the driver in alt_sys_init() +set_sw_property auto_initialize true + +# Location in generated BSP that sources will be copied into +set_sw_property bsp_subdirectory drivers + +# +# Source file listings... +# + +# C/C++ source files +add_sw_property c_source HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c + +# Include files +add_sw_property include_source HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h + +# This driver supports HAL type +add_sw_property supported_bsp_type HAL + +# End of file + diff --git a/ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h b/ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h new file mode 100644 index 0000000..4e1dbef --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/HAL/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h @@ -0,0 +1,166 @@ +#ifndef __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ +#define __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define SD_RAW_IFACE + +/* + * Device structure definition. Each instance of the driver uses one + * of these structures to hold its associated state. + */ +typedef struct alt_up_sd_card_dev { + /// @brief character mode device structure + /// @sa Developing Device Drivers for the HAL in Nios II Software Developer's Handbook + alt_dev dev; + /// @brief the base address of the device + unsigned int base; + +} alt_up_sd_card_dev; + +#ifndef bool + typedef enum e_bool { false = 0, true = 1 } bool; +#endif + +////////////////////////////////////////////////////////////////////////// +// HAL system functions + +alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char *name); +/* Open an SD Card Interface if it is connected to the system. */ + + +bool alt_up_sd_card_is_Present(void); +/* Check if there is an SD Card insterted into the SD Card socket. + */ + +#ifndef SD_RAW_IFACE +bool alt_up_sd_card_is_FAT16(void); +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + */ + + +short int alt_up_sd_card_fopen(char *name, bool create); +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + * + * Inputs: + * name - a file name including a directory, relative to the root directory + * create - a flag set to true to create a file if it does not already exist + * Output: + * An index to the file record assigned to the specified file. -1 is returned if the file could not be opened. + */ + + +short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name); +/* This function sets up a search algorithm to go through a given directory looking for files. + * If the search directory is valid, then the function searches for the first file it finds. + * Inputs: + * directory_to_search_through - name of the directory to search through + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * 0 - success + * 1 - invalid directory + * 2 - No card or incorrect card format. + * + * To specify a directory give the name in a format consistent with the following regular expression: + * [{[valid_chars]+}/]*. + * + * In other words, give a path name starting at the root directory, where each directory name is followed by a '/'. + * Then, append a '.' to the directory name. Examples: + * "." - look through the root directory + * "first/." - look through a directory named "first" that is located in the root directory. + * "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory. + * Invalid examples include: + * "/.", "/////." - this is not the root directory. + * "/first/." - the first character may not be a '/'. + */ + + + +short int alt_up_sd_card_find_next(char *file_name); +/* This function searches for the next file in a given directory, as specified by the find_first function. + * Inputs: + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * -1 - end of directory. + * 0 - success + * 2 - No card or incorrect card format. + * 4 - find_first has not been called successfully. + */ + +void alt_up_sd_card_set_attributes(short int file_handle, short int attributes); +/* Set file attributes as needed. + */ + +short int alt_up_sd_card_get_attributes(short int file_handle); +/* Return file attributes, or -1 if the file_handle is invalid. + */ + + +short int alt_up_sd_card_read(short int file_handle); +/* Read a single character from the given file. Return -1 if at the end of a file. Any other negative number + * means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */ + + +bool alt_up_sd_card_write(short int file_handle, char byte_of_data); +/* Write a single character to a given file. Return true if successful, and false otherwise. */ + + +bool alt_up_sd_card_fclose(short int file_handle); +// This function closes an opened file and saves data to SD Card if necessary. + +#else +bool Write_Sector_Data(int sector_index, int partition_offset); +bool Save_Modified_Sector(); +bool Read_Sector_Data(int sector_index, int partition_offset); +#endif //SD_RAW_IFACE + +////////////////////////////////////////////////////////////////////////// +// file-like operation functions + +////////////////////////////////////////////////////////////////////////// +// direct operation functions + + +/* + * Macros used by alt_sys_init + */ +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INSTANCE(name, device) \ + static alt_up_sd_card_dev device = \ + { \ + { \ + ALT_LLIST_ENTRY, \ + name##_NAME, \ + NULL , /* open */ \ + NULL , /* close */ \ + NULL, /* read */ \ + NULL, /* write */ \ + NULL , /* lseek */ \ + NULL , /* fstat */ \ + NULL , /* ioctl */ \ + }, \ + name##_BASE, \ + } + +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INIT(name, device) \ +{ \ + alt_dev_reg(&device.dev); \ +} + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ */ + + diff --git a/ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c b/ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c new file mode 100644 index 0000000..b98e077 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/HAL/src/Altera_UP_SD_Card_Avalon_Interface_mod.c @@ -0,0 +1,1908 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include +#include +#include "Altera_UP_SD_Card_Avalon_Interface_mod.h" + +/////////////////////////////////////////////////////////////////////////// +// Local Define Statements +/////////////////////////////////////////////////////////////////////////// + +#define CHAR_TO_UPPER(ch) ((char) (((ch >= 'a') && (ch <= 'z')) ? ((ch-'a')+'A'): ch)) + +// Data Buffer Address +#define SD_CARD_BUFFER(base, x) (base + x) +// 128-bit Card Identification Number +#define SD_CARD_CID(base, x) (base + 0x0200 + x) +// 128-bit Card Specific Data Register +#define SD_CARD_CSD(base, x) (base + 0x0210 + x) +// 32-bit Operating Conditions Register +#define SD_CARD_OCR(base) (base + 0x0220) +// 32-bit Card Status Register +#define SD_CARD_STATUS(base) (base + 0x0224) +// 16-bit Relative Card Address Register +#define SD_CARD_RCA(base) (base + 0x0228) +// 32-bit Card Argument Register +#define SD_CARD_ARGUMENT(base) (base + 0x022C) +// 16-bit Card Command Register +#define SD_CARD_COMMAND(base) (base + 0x0230) +// 16-bit Card Auxiliary Status Register +#define SD_CARD_AUX_STATUS(base) (base + 0x0234) +// 32-bit R1 Response Register +#define SD_CARD_R1_RESPONSE(base) (base + 0x0238) + +#define CMD_READ_BLOCK 17 +#define CMD_WRITE_BLOCK 24 + +// FAT 12/16 related stuff +//#define BOOT_SECTOR_DATA_SIZE 0x005A +#define MAX_FILES_OPENED 2 + +/******************************************************************************/ +/****** LOCAL DATA STRUCTURES ***********************************************/ +/******************************************************************************/ + + +typedef struct s_FAT_12_16_boot_sector { + unsigned char jump_instruction[3]; + char OEM_name[8]; + unsigned short int sector_size_in_bytes; + unsigned char sectors_per_cluster; + unsigned short int reserved_sectors; + unsigned char number_of_FATs; + unsigned short int max_number_of_dir_entires; + unsigned short int number_of_sectors_in_partition; + unsigned char media_descriptor; + unsigned short int number_of_sectors_per_table; + unsigned short int number_of_sectors_per_track; + unsigned short int number_of_heads; + unsigned int number_of_hidden_sectors; + unsigned int total_sector_count_if_above_32MB; + unsigned char drive_number; + unsigned char current_head; + unsigned char boot_signature; + unsigned char volume_id[4]; + char volume_label[11]; + unsigned char file_system_type[8]; + unsigned char bits_for_cluster_index; + unsigned int first_fat_sector_offset; + unsigned int second_fat_sector_offset; + unsigned int root_directory_sector_offset; + unsigned int data_sector_offset; +} t_FAT_12_16_boot_sector; + + +typedef struct s_file_record { + unsigned char name[8]; + unsigned char extension[3]; + unsigned char attributes; + unsigned short int create_time; + unsigned short int create_date; + unsigned short int last_access_date; + unsigned short int last_modified_time; + unsigned short int last_modified_date; + unsigned short int start_cluster_index; + unsigned int file_size_in_bytes; + /* The following fields are only used when a file has been created or opened. */ + unsigned int current_cluster_index; + unsigned int current_sector_in_cluster; + unsigned int current_byte_position; + // Absolute location of the file record on the SD Card. + unsigned int file_record_cluster; + unsigned int file_record_sector_in_cluster; + short int file_record_offset; + // Is this record in use and has the file been modified. + unsigned int home_directory_cluster; + bool modified; + bool in_use; +} t_file_record; + + +typedef struct s_find_data { + unsigned int directory_root_cluster; // 0 means root directory. + unsigned int current_cluster_index; + unsigned int current_sector_in_cluster; + short int file_index_in_sector; + bool valid; +} t_find_data; + + +/////////////////////////////////////////////////////////////////////////// +// Local Variables +/////////////////////////////////////////////////////////////////////////// + + +bool initialized = false; +bool is_sd_card_formated_as_FAT16 = false; +volatile short int *aux_status_register = NULL; +volatile int *status_register = NULL; +volatile short int *CSD_register_w0 = NULL; +volatile short int *command_register = NULL; +volatile int *command_argument_register = NULL; +volatile char *buffer_memory = NULL; +int fat_partition_offset_in_512_byte_sectors = 0; +int fat_partition_size_in_512_byte_sectors = 0; + +#ifndef SD_RAW_IFACE +t_FAT_12_16_boot_sector boot_sector_data; +#endif + +alt_up_sd_card_dev *device_pointer = NULL; + +#ifndef SD_RAW_IFACE +// Pointers to currently opened files. +t_file_record active_files[MAX_FILES_OPENED]; +#endif +bool current_sector_modified = false; +unsigned int current_sector_index = 0; + +#ifndef SD_RAW_IFACE +t_find_data search_data; +#endif + + +/////////////////////////////////////////////////////////////////////////// +// Local Functions +/////////////////////////////////////////////////////////////////////////// + +#ifndef SD_RAW_IFACE +static bool Write_Sector_Data(int sector_index, int partition_offset) +#else +bool Write_Sector_Data(int sector_index, int partition_offset) +#endif +// This function writes a sector at the specified address on the SD Card. +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + short int reg_state = 0xff; + + /* Multiply sector offset by sector size to get the address. Sector size is 512. Also, + * the SD card reads data in 512 byte chunks, so the address must be a multiple of 512. */ + IOWR_32DIRECT(command_argument_register, 0, (sector_index + partition_offset)*512); + IOWR_16DIRECT(command_register, 0, CMD_WRITE_BLOCK); + do { + reg_state = (short int) IORD_16DIRECT(aux_status_register,0); + } while ((reg_state & 0x04)!=0); + // Make sure the request did not time out. + if ((reg_state & 0x10) == 0) + { + result = true; + current_sector_modified = false; + current_sector_index = sector_index+partition_offset; + } + } + return result; +} + +#ifndef SD_RAW_IFACE +static bool Save_Modified_Sector() +#else +bool Save_Modified_Sector() +#endif +// If the sector has been modified, then save it to the SD Card. +{ + bool result = true; + if (current_sector_modified) + { + result = Write_Sector_Data(current_sector_index, 0); + } + return result; +} + +#ifndef SD_RAW_IFACE +static bool Read_Sector_Data(int sector_index, int partition_offset) +#else +bool Read_Sector_Data(int sector_index, int partition_offset) +#endif +// This function reads a sector at the specified address on the SD Card. +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + short int reg_state = 0xff; + + /* Write data to the SD card if the current buffer is out of date. */ + if (current_sector_modified) + { + if (Write_Sector_Data(current_sector_index, 0) == false) + { + return false; + } + } + /* Multiply sector offset by sector size to get the address. Sector size is 512. Also, + * the SD card reads data in 512 byte chunks, so the address must be a multiple of 512. */ + IOWR_32DIRECT(command_argument_register, 0, (sector_index + partition_offset)*512); + IOWR_16DIRECT(command_register, 0, CMD_READ_BLOCK); + do { + reg_state = (short int) IORD_16DIRECT(aux_status_register,0); + } while ((reg_state & 0x04)!=0); + // Make sure the request did not time out. + if ((reg_state & 0x10) == 0) + { + result = true; + current_sector_modified = false; + current_sector_index = sector_index+partition_offset; + } + } + return result; +} + +#ifndef SD_RAW_IFACE +static bool get_cluster_flag(unsigned int cluster_index, unsigned short int *flag) +// Read a cluster flag. +{ + unsigned int sector_index = (cluster_index / 256) + fat_partition_offset_in_512_byte_sectors; + + sector_index = sector_index + boot_sector_data.first_fat_sector_offset; + + if (sector_index != current_sector_index) + { + if (Read_Sector_Data(sector_index, 0) == false) + { + return false; + } + } + *flag = (unsigned short int) IORD_16DIRECT(device_pointer->base, 2*(cluster_index % 256)); + return true; +} + + +static bool mark_cluster(unsigned int cluster_index, short int flag, bool first_fat) +// Place a marker on the specified cluster in a given FAT. +{ + unsigned int sector_index = (cluster_index / 256) + fat_partition_offset_in_512_byte_sectors; + + if (first_fat) + { + sector_index = sector_index + boot_sector_data.first_fat_sector_offset; + } + else + { + sector_index = sector_index + boot_sector_data.second_fat_sector_offset; + } + + if (sector_index != current_sector_index) + { + if (Read_Sector_Data(sector_index, 0) == false) + { + return false; + } + } + IOWR_16DIRECT(device_pointer->base, 2*(cluster_index % 256), flag); + current_sector_modified = true; + return true; +} + + +static bool Check_for_Master_Boot_Record(void) +// This function reads the first 512 bytes on the SD Card. This data should +// contain the Master Boot Record. If it does, then print +// relevant information and return true. Otherwise, return false. +{ + bool result = false; + int index; + int end, offset, partition_size; + + /* Load the first 512 bytes of data from SD card. */ + if (Read_Sector_Data(0, 0)) + { + end = (short int) IORD_16DIRECT(device_pointer->base,0x1fe); + + // Check if the end of the sector contains an end string 0xaa55. + if ((end & 0x0000ffff) == 0x0000aa55) + { + // Check four partition entries and see if any are valid + for (index = 0; index < 4; index++) + { + int partition_data_offset = (index * 16) + 0x01be; + char type; + + // Read Partition type + type = (unsigned char) IORD_8DIRECT(device_pointer->base,partition_data_offset + 0x04); + + // Check if this is an FAT parition + if ((type == 1) || (type == 4) || (type == 6) || (type == 14)) + { + // Get partition offset and size. + offset = (((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0A)) << 16) | ((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x08)); + partition_size = (((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0E)) << 16) | ((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0C)); + + // Check if the partition is valid + if (partition_size > 0) + { + result = true; + fat_partition_size_in_512_byte_sectors = partition_size; + fat_partition_offset_in_512_byte_sectors = offset; + break; + } + } + } + } + } + + return result; +} + + +static bool Read_File_Record_At_Offset(int offset, t_file_record *record, unsigned int cluster_index, unsigned int sector_in_cluster) +// This function reads a file record +{ + bool result = false; + if (((offset & 0x01f) == 0) && (alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + int counter; + + for (counter = 0; counter < 8; counter++) + { + record->name[counter] = (char) IORD_8DIRECT(device_pointer->base, offset+counter); + } + for (counter = 0; counter < 3; counter++) + { + record->extension[counter] = (char) IORD_8DIRECT(device_pointer->base, offset+counter+8); + } + record->attributes = (char) IORD_8DIRECT(device_pointer->base, offset+11); + /* Ignore reserved bytes at locations 12 and 13. */ + record->create_time = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+14); + record->create_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+16); + record->last_access_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+18); + /* Ignore reserved bytes at locations 20 and 21. */ + record->last_modified_time = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+22); + record->last_modified_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+24); + record->start_cluster_index = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+26); + record->file_size_in_bytes = (unsigned int) IORD_32DIRECT(device_pointer->base, offset+28); + record->file_record_cluster = cluster_index; + record->file_record_sector_in_cluster = sector_in_cluster; + record->file_record_offset = offset; + result = true; + } + return result; +} + + +static bool Write_File_Record_At_Offset(int offset, t_file_record *record) +// This function writes a file record at a given offset. The offset is given in bytes. +{ + bool result = false; + if (((offset & 0x01f) == 0) && (alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + int counter; + + for (counter = 0; counter < 8; counter=counter+2) + { + short int two_chars = (short int) record->name[counter+1]; + two_chars = two_chars << 8; + two_chars = two_chars | record->name[counter]; + IOWR_16DIRECT(device_pointer->base, offset+counter, two_chars); + } + for (counter = 0; counter < 3; counter++) + { + IOWR_8DIRECT(device_pointer->base, offset+counter+8, record->extension[counter]); + } + IOWR_8DIRECT(device_pointer->base, offset+11, record->attributes); + /* Ignore reserved bytes at locations 12 and 13. */ + IOWR_16DIRECT(device_pointer->base, offset+14, record->create_time); + IOWR_16DIRECT(device_pointer->base, offset+16, record->create_date); + IOWR_16DIRECT(device_pointer->base, offset+18, record->last_access_date); + /* Ignore reserved bytes at locations 20 and 21. */ + IOWR_16DIRECT(device_pointer->base, offset+22, record->last_modified_time); + IOWR_16DIRECT(device_pointer->base, offset+24, record->last_modified_date); + IOWR_16DIRECT(device_pointer->base, offset+26, record->start_cluster_index); + IOWR_32DIRECT(device_pointer->base, offset+28, record->file_size_in_bytes); + current_sector_modified = true; + result = true; + } + return result; +} + + +static bool Check_for_DOS_FAT(int FAT_partition_start_sector) +// This function reads the boot sector for the FAT file system on the SD Card. +// The offset_address should point to the sector on the card where the boot sector is located. +// The sector number is specified either in the master Boot Record, or is 0 by default for a purely FAT +// based file system. If the specified sector contains a FAT boot sector, then this function prints the +// relevant information and returns 1. Otherwise, it returns 0. +{ + bool result = false; + int counter = 0; + short int end; + + result = Read_Sector_Data(0, FAT_partition_start_sector); + end = (short int) IORD_16DIRECT(device_pointer->base, 0x1fe); + if (((end & 0x0000ffff) == 0x0000aa55) && (result)) + { + int num_clusters = 0; + + boot_sector_data.jump_instruction[0] = (char) IORD_8DIRECT(device_pointer->base, 0); + boot_sector_data.jump_instruction[1] = (char) IORD_8DIRECT(device_pointer->base, 1); + boot_sector_data.jump_instruction[2] = (char) IORD_8DIRECT(device_pointer->base, 2); + for (counter = 0; counter < 8; counter++) + { + boot_sector_data.OEM_name[counter] = (char) IORD_8DIRECT(device_pointer->base, 3+counter); + } + boot_sector_data.sector_size_in_bytes = (((unsigned char) IORD_8DIRECT(device_pointer->base, 12)) << 8 ) | ((char) IORD_8DIRECT(device_pointer->base, 11)); + boot_sector_data.sectors_per_cluster = ((unsigned char) IORD_8DIRECT(device_pointer->base, 13)); + boot_sector_data.reserved_sectors = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 14)); + boot_sector_data.number_of_FATs = ((unsigned char) IORD_8DIRECT(device_pointer->base, 16)); + boot_sector_data.max_number_of_dir_entires = (((unsigned short int)(((unsigned char) IORD_8DIRECT(device_pointer->base, 18)))) << 8 ) | ((unsigned char) IORD_8DIRECT(device_pointer->base, 17)); + boot_sector_data.number_of_sectors_in_partition = (((unsigned short int)(((unsigned char) IORD_8DIRECT(device_pointer->base, 20)))) << 8 ) | ((unsigned char) IORD_8DIRECT(device_pointer->base, 19)); + boot_sector_data.media_descriptor = ((unsigned char) IORD_8DIRECT(device_pointer->base, 21)); + boot_sector_data.number_of_sectors_per_table = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 22)); + boot_sector_data.number_of_sectors_per_track = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 24)); + boot_sector_data.number_of_heads = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 26)); + boot_sector_data.number_of_hidden_sectors = ((unsigned int) IORD_32DIRECT(device_pointer->base, 28)); + boot_sector_data.total_sector_count_if_above_32MB = ((unsigned int) IORD_32DIRECT(device_pointer->base, 32)); + boot_sector_data.drive_number = ((unsigned char) IORD_8DIRECT(device_pointer->base, 36)); + boot_sector_data.current_head = ((unsigned char) IORD_8DIRECT(device_pointer->base, 37)); + boot_sector_data.boot_signature = ((unsigned char) IORD_8DIRECT(device_pointer->base, 38)); + boot_sector_data.first_fat_sector_offset = boot_sector_data.reserved_sectors; + boot_sector_data.second_fat_sector_offset = boot_sector_data.first_fat_sector_offset + boot_sector_data.number_of_sectors_per_table; + boot_sector_data.root_directory_sector_offset = boot_sector_data.second_fat_sector_offset + boot_sector_data.number_of_sectors_per_table; + boot_sector_data.data_sector_offset = boot_sector_data.root_directory_sector_offset + (32*boot_sector_data.max_number_of_dir_entires / boot_sector_data.sector_size_in_bytes); + + if (boot_sector_data.number_of_sectors_in_partition > 0) + { + num_clusters = (boot_sector_data.number_of_sectors_in_partition / boot_sector_data.sectors_per_cluster); + } + else + { + num_clusters = (boot_sector_data.total_sector_count_if_above_32MB / boot_sector_data.sectors_per_cluster); + } + if (num_clusters < 4087) + { + boot_sector_data.bits_for_cluster_index = 12; + } + else if (num_clusters <= 65517) + { + boot_sector_data.bits_for_cluster_index = 16; + } + else + { + boot_sector_data.bits_for_cluster_index = 32; + } + + for (counter = 0; counter < 4; counter++) + { + boot_sector_data.volume_id[counter] = ((char) IORD_8DIRECT(device_pointer->base, 39+counter)); + } + for (counter = 0; counter < 11; counter++) + { + boot_sector_data.volume_label[counter] = ((char) IORD_8DIRECT(device_pointer->base, 43+counter)); + } + for (counter = 0; counter < 8; counter++) + { + boot_sector_data.file_system_type[counter] = ((char) IORD_8DIRECT(device_pointer->base, 54+counter)); + } + // Clear file records + for (counter = 0; counter < MAX_FILES_OPENED; counter++) + { + active_files[counter].in_use = false; + } + result = true; + } + else + { + result = false; + } + return result; +} + + +static bool Look_for_FAT16(void) +// Read the SD card to determine if it contains a FAT16 partition. +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + short int csd_file_format = *CSD_register_w0; + + fat_partition_offset_in_512_byte_sectors = 0; + fat_partition_size_in_512_byte_sectors = 0; + + if (((csd_file_format & 0x8000) == 0) && ((csd_file_format & 0x0c00) != 0x0c00)) + { + if ((csd_file_format & 0x0c00) == 0x0400) + { + /* SD Card contains files stored in a DOS FAT (floppy like) file format, without a partition table */ + result = Check_for_DOS_FAT(0); + } + if ((csd_file_format & 0x0c00) == 0x0000) + { + /* SD Card contains files stored in a Hard disk-like file format that contains a partition table */ + if (Check_for_Master_Boot_Record()) + { + result = Check_for_DOS_FAT(fat_partition_offset_in_512_byte_sectors); + } + } + if (result == true) + { + // Accept only FAT16, not FAT12. + if (boot_sector_data.bits_for_cluster_index != 16) + { + result = false; + } + else + { + fat_partition_size_in_512_byte_sectors = boot_sector_data.number_of_sectors_in_partition; + } + } + } + } + return result; +} + + +static void filename_to_upper_case(char *file_name) +// Change file name to upper case. +{ + int index; + int length = strlen(file_name); + + for (index = 0; index < length; index++) + { + if ((file_name[index] >= 'a') && (file_name[index] <= 'z')) + { + file_name[index] = (file_name[index] - 'a') + 'A'; + } + } +} + + +static bool check_file_name_for_FAT16_compliance(char *file_name) +// Check if the file complies with FAT16 naming convention. +{ + int length = strlen(file_name); + int index; + int last_dir_break_position = -1; + int last_period = -1; + bool result = true; + + for(index = 0; index < length; index++) + { + if ((file_name[index] == ' ') || + ((last_dir_break_position == (index - 1)) && ((file_name[index] == '\\') || (file_name[index] == '/'))) || + ((index - last_period == 9) && (file_name[index] != '.')) || + ((last_dir_break_position != last_period) && (index - last_period > 3) && + (file_name[index] != '\\') && (file_name[index] != '/')) + ) + { + result = false; + break; + } + if ((file_name[index] == '\\') || (file_name[index] == '/')) + { + last_period = index; + last_dir_break_position = index; + } + if (file_name[index] == '.') + { + last_period = index; + } + } + if ((file_name[length-1] == '\\') || (file_name[length-1] == '/')) + { + result = false; + } + return result; +} + + +static int get_dir_divider_location(char *name) +// Find a directory divider location. +{ + int index = 0; + int length = strlen(name); + + for(index = 0; index < length; index++) + { + if ((name[index] == '\\') || (name[index] == '/')) + { + break; + } + } + + if (index == length) + { + index = -1; + } + + return index; +} + + +static bool match_file_record_to_name_ext(t_file_record *file_record, char *name, char *extension) +/* See if the given name and extension match the file record. Return true if this is so, false otherwise. */ +{ + bool match = true; + int index; + + for (index = 0; index < 8; index++) + { + if (CHAR_TO_UPPER(file_record->name[index]) != CHAR_TO_UPPER(name[index])) + { + match = false; + break; + } + } + for (index = 0; index < 3; index++) + { + if (CHAR_TO_UPPER(file_record->extension[index]) != CHAR_TO_UPPER(extension[index])) + { + match = false; + break; + } + } + return match; +} + + +static bool get_home_directory_cluster_for_file(char *file_name, int *home_directory_cluster, t_file_record *file_record) +// Scan the directories in given in the file name and find the root directory for the file. +{ + bool result = false; + int home_dir_cluster = 0; + int location, index; + int start_location = 0; + + /* Get Next Directory. */ + location = get_dir_divider_location( file_name ); + while (location > 0) + { + char name[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; + char extension[3] = { ' ', ' ', ' ' }; + int ext_index = -1; + int new_cluster = home_dir_cluster; + + // Get the name of the directory in name/extension format. + for (index = 0; index < location; index++) + { + if (file_name[index+start_location] == '.') + { + ext_index = index; + } + else if (ext_index < 0) + { + name[index] = file_name[index+start_location]; + } + else + { + extension[index-ext_index] = file_name[index+start_location]; + } + } + + if (home_dir_cluster == 0) + { + /* We are in the root directory. Scan the directory (of predefined size) and see if you can find the specified file. */ + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index; + + for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data(sector_index+boot_sector_data.root_directory_sector_offset, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, 0, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + if (match) + { + new_cluster = file_record->start_cluster_index; + file_record->file_record_cluster = 1; // Home directory is a subdirectory in the root directory. + break; + } + } + } + } + else + { + break; + } + if (new_cluster != home_dir_cluster) + { + break; + } + } + if (new_cluster != home_dir_cluster) + { + // A valid directory is found, so go to it. + home_dir_cluster = new_cluster; + start_location = start_location+location+1; + } + else + { + // Directory path is invalid. + return false; + } + } else { + // This is a subdirectory that can have any number of elements. So scan through it as though it was a file + // and see if you can find the directory of interest. + int cluster = home_dir_cluster; + + do { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index; + + for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, cluster, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + if (match) + { + new_cluster = file_record->start_cluster_index; + break; + } + } + } + } + else + { + break; + } + if (new_cluster != home_dir_cluster) + { + break; + } + } + // If this is the end of the cluster and the directory has not been found, then see if there is another cluster + // that holds data for the current directory. + if (new_cluster == home_dir_cluster) + { + unsigned short int next_cluster; + + if (get_cluster_flag(new_cluster, &next_cluster)) + { + // The directory needs to be expanded to store more files. + if ((next_cluster & 0x0000fff8) == 0x0000fff8) + { + return false; + } + new_cluster = (next_cluster & 0x0000fff8); + } + else + { + // Directory path is invalid. + return false; + } + } + } while ((cluster < 0x0000fff8) && (new_cluster == home_dir_cluster)); + if (new_cluster != home_dir_cluster) + { + // A valid directory is found, so go to it. + home_dir_cluster = new_cluster; + start_location = start_location+location+1; + } + else + { + // Directory path is invalid. + return false; + } + } + location = get_dir_divider_location(&(file_name[start_location])); + if (location < 0) + { + // Directory has been located. + result = true; + } + } + + *home_directory_cluster = home_dir_cluster; + if (home_dir_cluster == 0) + { + file_record->file_record_cluster = 0; // Home directory is the root directory. + result = true; + } + return result; +} + + +static bool find_file_in_directory(int directory_start_cluster, char *file_name, t_file_record *file_record) +// Given a cluster and a file name, check if the file already exists. Return the file record if the file is found. +{ + int location = get_dir_divider_location( file_name ); + int last_dir_separator = 0; + char name[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; + char extension[3] = { ' ', ' ', ' ' }; + int ext_index = -1; + int cluster = directory_start_cluster; + int index; + int length = strlen(file_name); + bool result = false; + + // Skip through all directory separators. + while (location > 0) + { + last_dir_separator = last_dir_separator+location+1; + location = get_dir_divider_location( &(file_name[last_dir_separator]) ); + } + + // Get the name of the file in name/extension format. + for (index = last_dir_separator; index < length; index++) + { + if (file_name[index] == '.') + { + ext_index = index; + } + else if (ext_index < 0) + { + name[index-last_dir_separator] = file_name[index]; + } + else + { + extension[index-ext_index-1] = file_name[index]; + } + } + + // Look for the file. + if (directory_start_cluster == 0) + { + /* We are in the root directory. Scan the directory (of predefined size) and see if you can find the specified file. */ + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index; + + for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, + fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, 0, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + + if (match) + { + result = true; + break; + } + } + } + } + else + { + break; + } + if (result) + { + break; + } + } + } + else + { + do { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index; + + for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, cluster, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + + if (match) + { + result = true; + break; + } + } + } + } + else + { + break; + } + if (result) + { + break; + } + } + // If this is the end of the cluster and the file has not been found, then see if there is another cluster + // that holds data for the current directory. + if (result == false) + { + unsigned short int new_cluster; + + if (get_cluster_flag(cluster, &new_cluster)) + { + // The directory needs to be expanded to store more files. + if ((new_cluster & 0x0000fff8) == 0x0000fff8) + { + return false; + } + cluster = (new_cluster & 0x0000fff8); + } + else + { + // Directory path is invalid. + return false; + } + } + } while ((cluster < 0x0000fff8) && (result == false)); + } + + return result; +} + + +static bool find_first_empty_cluster(unsigned int *cluster_number) +// Find the first empty cluster. It will be marked by a 0 entry in the File Allocation Table. +{ + unsigned int sector = boot_sector_data.first_fat_sector_offset; + unsigned int cluster_index = 2; + short int cluster = -1; + bool result = false; + unsigned max_cluster_index = 0; + unsigned int non_data_sectors = boot_sector_data.data_sector_offset; + unsigned int less_than_32 = boot_sector_data.number_of_sectors_in_partition; + unsigned int greater_than_32 = boot_sector_data.total_sector_count_if_above_32MB; + + if (less_than_32 > greater_than_32) + { + max_cluster_index = ((less_than_32 - non_data_sectors) / boot_sector_data.sectors_per_cluster) + 1; + } + else + { + max_cluster_index = ((greater_than_32 - non_data_sectors) / boot_sector_data.sectors_per_cluster) + 1; + } + // Find an empty cluster for the file. + while (sector != boot_sector_data.second_fat_sector_offset) + { + if (Read_Sector_Data( sector, fat_partition_offset_in_512_byte_sectors)) + { + do { + cluster = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 2*(cluster_index % 256))); + if (cluster == 0) + { + // Free cluster found. + break; + } + else + { + cluster_index++; + } + } while ((cluster_index % 256) != 0); + } + if (cluster == 0) + { + break; + } + sector++; + } + if ((cluster == 0) && (cluster <= max_cluster_index)) + { + *cluster_number = cluster_index; + result = true; + } + return result; +} + + +static int find_first_empty_record_in_a_subdirectory(int start_cluster_index) +// Search for a free spot in a subdirectory. Return an encoded location for the file record. +{ + int result = -1; + int cluster = start_cluster_index; + do { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index; + + for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + unsigned short int leading_char; + + // Read file record. + leading_char = ((unsigned char) IORD_8DIRECT(device_pointer->base, file_counter*32)); + if ((leading_char == 0x00e5) || (leading_char == 0)) + { + result = (cluster) | ((sector_index*16 + file_counter) << 16); + return result; + } + } + } + else + { + break; + } + } + // If this is the end of the cluster and the file has not been found, then see if there is another cluster + // that holds data for the current directory. + if (result < 0) + { + unsigned short int new_cluster; + if (get_cluster_flag(cluster, &new_cluster)) + { + // The directory needs to be expanded to store more files. + if ((new_cluster & 0x0000fff8) == 0x0000fff8) + { + unsigned int new_dir_cluster; + if (find_first_empty_cluster(&new_dir_cluster)) + { + // Add the new cluster to the linked list of the given directory. + if (mark_cluster(cluster, ((short int) (new_dir_cluster)), true) && + mark_cluster(new_dir_cluster, ((short int) (0xffff)), true) && + mark_cluster(cluster, ((short int) (new_dir_cluster)), false) && + mark_cluster(new_dir_cluster, ((short int) (0xffff)), false)) + { + Save_Modified_Sector(); + // The new file will begin at the first entry of the directory. + result = new_dir_cluster; + } + } + cluster = (new_cluster & 0x0000fff8); + } + } + else + { + // Error encountered. + result = -1; + } + } + } while ((cluster < 0x0000fff8) && (result == -1)); + return result; +} + + +static int find_first_empty_record_in_root_directory() +// Find a first unused record location to use. Return -1 if none is found. +{ + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index; + int result = -1; + + for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, + fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + unsigned short int leading_char; + + // Read first character of the file record. + leading_char = ((unsigned char) IORD_8DIRECT(device_pointer->base, file_counter*32)); + if ((leading_char == 0x00e5) || (leading_char == 0)) + { + result = (sector_index*16 + file_counter) << 16; + return result; + } + } + } + else + { + break; + } + } + return result; +} + +static void convert_filename_to_name_extension(char *filename, char *name, char *extension) +// This function converts the file name into a name . extension format. +{ + int counter; + int local = 0; + + for(counter = 0; counter < 8; counter++) + { + if (filename[local] != '.') + { + name[counter] = filename[local]; + if (filename[local] != 0) local++; + } + else + { + name[counter] = ' '; + } + } + if (filename[local] == '.') local++; + for(counter = 0; counter < 3; counter++) + { + if (filename[local] != 0) + { + extension[counter] = filename[local]; + local++; + } + else + { + extension[counter] = ' '; + } + } + +} + +static bool create_file(char *name, t_file_record *file_record, t_file_record *home_dir) +// Create a file in a given directory. Expand the directory if needed. +{ + unsigned int cluster_number; + bool result = false; + + if (find_first_empty_cluster(&cluster_number)) + { + int record_index; + + if (home_dir->file_record_cluster == 0) + { + // Put a file in the root directory. + record_index = find_first_empty_record_in_root_directory(); + } + else + { + // Put a file in a subdirectory. + record_index = find_first_empty_record_in_a_subdirectory(home_dir->start_cluster_index); + } + if (record_index >= 0) + { + unsigned int file_record_sector; + int location = get_dir_divider_location( name ); + int last_dir_separator = 0; + + // Skip through all directory separators. + while (location > 0) + { + last_dir_separator = last_dir_separator+location+1; + location = get_dir_divider_location( &(name[last_dir_separator]) ); + } + + convert_filename_to_name_extension(&(name[last_dir_separator]), (char *)file_record->name, (char *)file_record->extension); + + file_record->attributes = 0; + file_record->create_time = 0; + file_record->create_date = 0; + file_record->last_access_date = 0; + file_record->last_modified_time = 0; + file_record->last_modified_date = 0; + file_record->start_cluster_index = cluster_number; + file_record->file_size_in_bytes = 0; + file_record->current_cluster_index = cluster_number; + file_record->current_sector_in_cluster = 0; + file_record->current_byte_position = 0; + file_record->file_record_cluster = record_index & 0x0000ffff; + file_record->file_record_sector_in_cluster = ((record_index >> 16) & 0x0000ffff) / 16; + file_record->file_record_offset = (((record_index >> 16) & 0x0000ffff) % 16)*32; + file_record->home_directory_cluster = home_dir->start_cluster_index; + file_record->in_use = true; + file_record->modified = true; + // Now write the record at the specified location. + file_record_sector = (file_record->file_record_cluster == 0) ? + (boot_sector_data.root_directory_sector_offset + file_record->file_record_sector_in_cluster): + (boot_sector_data.data_sector_offset + (file_record->file_record_cluster-2)*boot_sector_data.sectors_per_cluster + + file_record->file_record_sector_in_cluster); + + if (Read_Sector_Data(file_record_sector, fat_partition_offset_in_512_byte_sectors)) + { + if (Write_File_Record_At_Offset(file_record->file_record_offset, file_record)) + { + Save_Modified_Sector(); + // Mark the first cluster of the file as the last cluster at first. + mark_cluster(cluster_number, ((short int) (0xffff)), true); + if (mark_cluster(cluster_number, ((short int) (0xffff)), false)) + { + result = true; + } + } + } + } + + } + return result; +} + + +static void copy_file_record_name_to_string(t_file_record *file_record, char *file_name) +/* Copy a file name from the file record to a given string */ +{ + int index; + int flength = 0; + + /* Copy file name.*/ + for (index = 0; index < 8; index++) + { + if (file_record->name[index] != ' ') + { + file_name[flength] = file_record->name[index]; + flength = flength + 1; + } + } + if (file_record->extension[0] != ' ') + { + file_name[flength] = '.'; + flength = flength + 1; + for (index = 0; index < 3; index++) + { + if (file_record->extension[index] != ' ') + { + file_name[flength] = file_record->extension[index]; + flength = flength + 1; + } + } + } + file_name[flength] = 0; +} +#endif //SD_RAW_IFACE + +/////////////////////////////////////////////////////////////////////////// +// Direct functions +/////////////////////////////////////////////////////////////////////////// + + +alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char* name) +{ + // find the device from the device list + // (see altera_hal/HAL/inc/priv/alt_file.h + // and altera_hal/HAL/src/alt_find_dev.c + // for details) + alt_up_sd_card_dev *dev = (alt_up_sd_card_dev *) alt_find_dev(name, &alt_dev_list); + + if (dev != NULL) + { + aux_status_register = ((short int *) SD_CARD_AUX_STATUS(dev->base)); + status_register = ((int *) SD_CARD_STATUS(dev->base)); + CSD_register_w0 = ((short int *) SD_CARD_CSD(dev->base, 0)); + command_register = ((short int *) SD_CARD_COMMAND(dev->base)); + command_argument_register = ((int *) SD_CARD_ARGUMENT(dev->base)); + buffer_memory = (char *) SD_CARD_BUFFER(dev->base, 0); + device_pointer = dev; + initialized = false; +#ifndef SD_RAW_IFACE + is_sd_card_formated_as_FAT16 = false; + search_data.valid = false; +#endif + } + return dev; +} + + +bool alt_up_sd_card_is_Present(void) +// Check if there is an SD Card insterted into the SD Card socket. +{ + bool result = false; + + if ((device_pointer != NULL) && ((IORD_16DIRECT(aux_status_register,0) & 0x02) != 0)) + { + result = true; + } + else if (initialized == true) + { + int index; + + initialized = false; +#ifndef SD_RAW_IFACE + search_data.valid = false; + is_sd_card_formated_as_FAT16 = false; + + for(index = 0; index < MAX_FILES_OPENED; index++) + { + active_files[index].in_use = false; + active_files[index].modified = false; + } +#endif + } + return result; +} + +#ifndef SD_RAW_IFACE +bool alt_up_sd_card_is_FAT16(void) +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + * If the card contains a FAT16 volume, the local data structures will be initialized to allow reading and writing + * to the SD card as though it was a hard drive. + */ +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + // Check if an SD Card is in the SD Card slot. + if (initialized == false) + { + // Now determine if the card is formatted as FAT 16. + is_sd_card_formated_as_FAT16 = Look_for_FAT16(); + initialized = is_sd_card_formated_as_FAT16; + search_data.valid = false; + } + result = is_sd_card_formated_as_FAT16; + } + else + { + // If not then you may as well not open the device. + initialized = false; + is_sd_card_formated_as_FAT16 = false; + } + + return result; +} + + +short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name) +/* This function sets up a search algorithm to go through a given directory looking for files. + * If the search directory is valid, then the function searches for the first file it finds. + * Inputs: + * directory_to_search_through - name of the directory to search through + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * 0 - success + * 1 - invalid directory + * 2 - No card or incorrect card format. + * + * To specify a directory give the name in a format consistent with the following regular expression: + * [{[valid_chars]+}/]*. + * + * In other words, give a path name starting at the root directory, where each directory name is followed by a '/'. + * Then, append a '.' to the directory name. Examples: + * "." - look through the root directory + * "first/." - look through a directory named "first" that is located in the root directory. + * "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory. + * Invalid examples include: + * "/.", "/////." - this is not the root directory. + * "/first/." - the first character may not be a '/'. + */ +{ + short int result = 2; + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + int home_directory_cluster; + t_file_record file_record; + + if (get_home_directory_cluster_for_file(directory_to_search_through, &home_directory_cluster, &file_record)) + { + search_data.directory_root_cluster = home_directory_cluster; + search_data.current_cluster_index = home_directory_cluster; + search_data.current_sector_in_cluster = 0; + search_data.file_index_in_sector = -1; + search_data.valid = true; + result = alt_up_sd_card_find_next(file_name); + } + else + { + result = 1; + } + } + return result; +} + + +short int alt_up_sd_card_find_next(char *file_name) +/* This function searches for the next file in a given directory, as specified by the find_first function. + * Inputs: + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * -1 - end of directory. + * 0 - success + * 2 - No card or incorrect card format. + * 3 - find_first has not been called successfully. + */ +{ + short int result = 2; + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + if (search_data.valid) + { + t_file_record file_record; + int cluster = search_data.current_cluster_index; + + if (cluster == 0) + { + // Searching through the root directory + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index = search_data.current_sector_in_cluster; + int file_counter = search_data.file_index_in_sector+1; + + for (; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, + fat_partition_offset_in_512_byte_sectors)) + { + for (; file_counter < 16; file_counter++) + { + if (Read_File_Record_At_Offset(file_counter*32, &file_record, 0, sector_index)) + { + if ((file_record.name[0] != 0) && (file_record.name[0] != 0xe5)) + { + /* Update search structure. */ + search_data.file_index_in_sector = file_counter; + search_data.current_sector_in_cluster = sector_index; + + /* Copy file name.*/ + copy_file_record_name_to_string(&file_record, file_name); + return 0; + } + } + } + file_counter = 0; + } + else + { + break; + } + } + result = -1; + } + else + { + int file_counter = search_data.file_index_in_sector+1; + do + { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index = search_data.current_sector_in_cluster; + + for (; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + for (; file_counter < 16; file_counter++) + { + if (Read_File_Record_At_Offset(file_counter*32, &file_record, cluster, sector_index)) + { + if ((file_record.name[0] != 0) && (file_record.name[0] != 0xe5)) + { + /* Update search structure. */ + search_data.current_cluster_index = cluster; + search_data.file_index_in_sector = file_counter; + search_data.current_sector_in_cluster = sector_index; + + /* Copy file name.*/ + copy_file_record_name_to_string(&file_record, file_name); + return 0; + } + } + } + file_counter = 0; + } + else + { + break; + } + } + // If this is the end of the cluster and the file has not been found, then see if there is another cluster + // that holds data for the current directory. + if (sector_index >= boot_sector_data.sectors_per_cluster) + { + unsigned short int new_cluster; + + if (get_cluster_flag(cluster, &new_cluster)) + { + if ((new_cluster & 0x0000fff8) == 0x0000fff8) + { + result = -1; + search_data.valid = false; + } + cluster = ((new_cluster) & 0x0000fff8); + } + else + { + // Error encountered. + result = -1; + } + } + } while (cluster < 0x0000fff8); + } + } + else + { + // Call Find_First first. + result = 3; + } + } + return result; +} + + +short int alt_up_sd_card_fopen(char *name, bool create) +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + * + * Inputs: + * name - a file name including a directory, relative to the root directory + * create - a flag set to true to create a file if it does not already exist + * Output: + * An index to the file record assigned to the specified file. -1 is returned if the file could not be opened. + * Return -2 if the specified file has already been opened previously. + */ +{ + short int file_record_index = -1; + + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + unsigned int home_directory_cluster = 0; + t_file_record home_dir; + + /* First check the file name format. It should not be longer than 12 characters, including a period and the extension. + * Rules: + * - no spaces + * - at most 12 chatacters per name, with a period in 9th position. + * - a / or a \ every at most 12 characters. + */ + filename_to_upper_case(name); + if (check_file_name_for_FAT16_compliance(name)) + { + int index; + + /* Get home directory cluster location for the specified file. 0 means root directory. */ + if (!get_home_directory_cluster_for_file(name, (int *) &home_directory_cluster, &home_dir)) + { + return file_record_index; + } + + /* Find a free file slot to store file specs in. */ + for (index = 0; index < MAX_FILES_OPENED; index++) + { + if (active_files[index].in_use == false) + { + file_record_index = index; + break; + } + } + if (file_record_index >= 0) + { + /* If file record is found, then look for the specified file. If the create flag is set to true + * and the file is not found, then it should be created in the current directory. + */ + + if (find_file_in_directory(home_directory_cluster, name, &(active_files[file_record_index]))) + { + if (create) + { + /* Do not allow overwriting existing files for now. */ + return -1; + } + active_files[file_record_index].current_cluster_index = active_files[file_record_index].start_cluster_index; + active_files[file_record_index].current_sector_in_cluster = 0; + active_files[file_record_index].current_byte_position = 0; + active_files[file_record_index].in_use = true; + active_files[file_record_index].modified = false; + + /* Check if the file has already been opened. */ + for (index = 0; index < MAX_FILES_OPENED; index++) + { + if ((file_record_index != index) && (active_files[index].in_use == true)) + { + if ((active_files[file_record_index].file_record_cluster == active_files[index].file_record_cluster) && + (active_files[file_record_index].file_record_sector_in_cluster == active_files[index].file_record_sector_in_cluster) && + (active_files[file_record_index].file_record_offset == active_files[index].file_record_offset)) + { + // file already in use. + file_record_index = -2; + break; + } + } + } + + } + else if (create) + { + /* Create file if needed. */ + if (create_file(name, &(active_files[file_record_index]), &home_dir)) + { + active_files[file_record_index].in_use = true; + active_files[file_record_index].modified = true; + } + else + { + /* If file creation fails then return an invalid file handle. */ + file_record_index = -1; + } + } + else + { + /* Otherwise the file could not be opened.*/ + file_record_index = -1; + } + } + } + } + + return file_record_index; +} + + +void alt_up_sd_card_set_attributes(short int file_handle, short int attributes) +/* Return file attributes, or -1 if the file_handle is invalid. + */ +{ + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + active_files[file_handle].attributes = ((char)(attributes & 0x00ff)); + } + } +} + + +short int alt_up_sd_card_get_attributes(short int file_handle) +/* Return file attributes, or -1 if the file_handle is invalid. + */ +{ + short int result = -1; + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + result = ((active_files[file_handle].attributes) & 0x00ff); + } + } + return result; +} + +short int alt_up_sd_card_read(short int file_handle) +/* Read a single character from a given file. Return -1 if at the end of a file. Any other negative number + * means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */ +{ + short int ch = -1; + + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + if (active_files[file_handle].current_byte_position < active_files[file_handle].file_size_in_bytes) + { + int data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + + if ((active_files[file_handle].current_byte_position > 0) && ((active_files[file_handle].current_byte_position % 512) == 0)) + { + // Read in a new sector of data. + if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) + { + // Go to the next cluster. + unsigned short int next_cluster; + if (get_cluster_flag(active_files[file_handle].current_cluster_index, &next_cluster)) + { + if ((next_cluster & 0x0000fff8) == 0x0000fff8) + { + /* End of file */ + return -1; + } + else + { + active_files[file_handle].current_cluster_index = next_cluster; + active_files[file_handle].current_sector_in_cluster = 0; + data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + } + } + else + { + return -2; + } + } + else + { + active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_sector_in_cluster + 1; + data_sector = data_sector + 1; + } + } + // Reading te first byte of the file. + if (current_sector_index != (data_sector + fat_partition_offset_in_512_byte_sectors)) + { + if (!Read_Sector_Data(data_sector, fat_partition_offset_in_512_byte_sectors)) + { + return -2; + } + } + + ch = (unsigned char) IORD_8DIRECT(buffer_memory, (active_files[file_handle].current_byte_position % 512)); + active_files[file_handle].current_byte_position = active_files[file_handle].current_byte_position + 1; + } + } + } + + return ch; +} + + +bool alt_up_sd_card_write(short int file_handle, char byte_of_data) +/* Write a single character to a given file. Return true if successful, and false otherwise. */ +{ + bool result = false; + + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + int data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + short int buffer_offset = active_files[file_handle].current_byte_position % boot_sector_data.sector_size_in_bytes; + + if (active_files[file_handle].current_byte_position < active_files[file_handle].file_size_in_bytes) + { + if ((active_files[file_handle].current_byte_position > 0) && (buffer_offset == 0)) + { + // Read in a new sector of data. + if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) + { + // Go to the next cluster. + unsigned short int next_cluster; + if (get_cluster_flag(active_files[file_handle].current_cluster_index, &next_cluster)) + { + if (next_cluster < 0x0000fff8) + { + active_files[file_handle].current_cluster_index = next_cluster; + active_files[file_handle].current_sector_in_cluster = 0; + data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + } + } + else + { + return false; + } + } + else + { + active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_sector_in_cluster + 1; + data_sector = data_sector + 1; + } + } + } + else + { + /* You are adding data to the end of the file, so increment its size and look for an additional data cluster if needed. */ + if ((active_files[file_handle].current_byte_position > 0) && (buffer_offset == 0)) + { + if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) + { + /* Find a new cluster if possible. */ + unsigned int cluster_number; + + if (find_first_empty_cluster(&cluster_number)) + { + // mark clusters in both File Allocation Tables. + mark_cluster(active_files[file_handle].current_cluster_index, ((unsigned short int) (cluster_number & 0x0000ffff)), true); + mark_cluster(cluster_number, 0xffff, true); + mark_cluster(active_files[file_handle].current_cluster_index, ((unsigned short int) (cluster_number & 0x0000ffff)), false); + mark_cluster(cluster_number, 0xffff, false); + // Change cluster index and sector index to compute a new data sector. + active_files[file_handle].current_cluster_index = cluster_number; + active_files[file_handle].current_sector_in_cluster = 0; + } + else + { + return false; + } + } + else + { + /* Read the next sector in the cluster and modify it. We only need to change the data_sector value. The actual read happens a few lines below. */ + active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_byte_position / boot_sector_data.sector_size_in_bytes; + } + data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + } + } + // Reading a data sector into the buffer. Note that changes to the most recently modified sector will be saved before + // a new sector is read from the SD Card. + if (current_sector_index != data_sector + fat_partition_offset_in_512_byte_sectors) + { + if (!Read_Sector_Data(data_sector, fat_partition_offset_in_512_byte_sectors)) + { + return false; + } + } + // Write a byte of data to the buffer. + IOWR_8DIRECT(buffer_memory, buffer_offset, byte_of_data); + active_files[file_handle].current_byte_position = active_files[file_handle].current_byte_position + 1; + + // Modify the file record only when necessary. + if (active_files[file_handle].current_byte_position >= active_files[file_handle].file_size_in_bytes) + { + active_files[file_handle].file_size_in_bytes = active_files[file_handle].file_size_in_bytes + 1; + active_files[file_handle].modified = true; + } + // Invaldiate the buffer to ensure that the buffer contents are written to the SD card whe nthe file is closed. + current_sector_modified = true; + result = true; + } + } + + return result; +} + + +bool alt_up_sd_card_fclose(short int file_handle) +// This function closes an opened file and saves data to SD Card if necessary. +{ + bool result = false; + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + if (active_files[file_handle].in_use) + { + if (active_files[file_handle].modified) + { + unsigned int record_sector = active_files[file_handle].file_record_sector_in_cluster; + if (active_files[file_handle].file_record_cluster == 0) + { + record_sector = record_sector + boot_sector_data.root_directory_sector_offset; + } + else + { + record_sector = record_sector + boot_sector_data.data_sector_offset + + (active_files[file_handle].file_record_cluster - 2)*boot_sector_data.sectors_per_cluster; + } + if (Read_Sector_Data(record_sector, fat_partition_offset_in_512_byte_sectors)) + { + if (Write_File_Record_At_Offset(active_files[file_handle].file_record_offset, &(active_files[file_handle]))) + { + // Make sure that the Data has been saved to the SD Card. + result = Save_Modified_Sector(); + } + } + } + active_files[file_handle].in_use = false; + result = true; + } + } + + return result; +} + +#endif //SD_RAW_IFACE diff --git a/ip/altera_up_sd_card_avalon_interface_mod/doc/SD_Card_Interface_for_SoPC_Builder.pdf b/ip/altera_up_sd_card_avalon_interface_mod/doc/SD_Card_Interface_for_SoPC_Builder.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1aa463d7520cd891f5e05f1a4660ce3c27209e23 GIT binary patch literal 252601 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

n3WMVQ%3!DO&n_V#0obzHN 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

q>rVhn-I96AaWU=bfR0$9-|4k=qM^KTe4e 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 Rf '0'); + else + if (rising_edge(i_clock)) then + if (i_sync_reset = '1') then + shift_register <= (OTHERS => '0'); + elsif (i_enable = '1') then + if (i_shift = '0') then + shift_register(0) <= i_datain XOR shift_register(15); + shift_register(4 downto 1) <= shift_register(3 downto 0); + shift_register(5) <= shift_register(4) XOR i_datain XOR shift_register(15); + shift_register(11 downto 6) <= shift_register(10 downto 5); + shift_register(12) <= shift_register(11) XOR i_datain XOR shift_register(15); + shift_register(15 downto 13) <= shift_register(14 downto 12); + else -- shift CRC out (no more calculation now) + shift_register(15 downto 1) <= shift_register(14 downto 0); + shift_register(0) <= '0'; + end if; + end if; + end if; + end if; + end process; + + o_dataout <= shift_register(15); + o_crcout <= shift_register; +end rtl; + + + diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd new file mode 100644 index 0000000..3ae9430 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_CRC7_Generator.vhd @@ -0,0 +1,76 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +--------------------------------------------------------------------------------------- +-- This generates the necessary 7-CRC for Command and Response +-- Implementation: serial input/parallel output +-- +-- When input stream ends, the crcout output is the CRC checksum for the input stream. +-- +-- NOTES/REVISIONS: +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity Altera_UP_SD_CRC7_Generator is + + port + ( + i_clock : in std_logic; + i_enable : in std_logic; + i_reset_n : in std_logic; + i_shift : in std_logic; + i_datain : in std_logic; + o_dataout : out std_logic; + o_crcout : out std_logic_vector(6 downto 0) + ); + +end entity; + +architecture rtl of Altera_UP_SD_CRC7_Generator is + + -- Local wires + -- REGISTERED + signal shift_register : std_logic_vector(6 downto 0); +begin + + process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + shift_register <= (OTHERS => '0'); + else + if (rising_edge(i_clock)) then + if (i_enable = '1') then + if (i_shift = '0') then + shift_register(0) <= i_datain XOR shift_register(6); + shift_register(1) <= shift_register(0); + shift_register(2) <= shift_register(1); + shift_register(3) <= shift_register(2) XOR i_datain XOR shift_register(6); + shift_register(4) <= shift_register(3); + shift_register(5) <= shift_register(4); + shift_register(6) <= shift_register(5); + else -- shift CRC out (no more calculation now) + shift_register(0) <= '0'; + shift_register(6 downto 1) <= shift_register(5 downto 0); + end if; + end if; + end if; + end if; + end process; + + o_dataout <= shift_register(6); + o_crcout <= shift_register; +end rtl; + diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd new file mode 100644 index 0000000..f9bb3b0 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_48_bit_Command_Generator.vhd @@ -0,0 +1,570 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +------------------------------------------------------------------------------------- +-- This module takes a command ID and data, and generates a 48-bit message for it. +-- It will first check if the command is a valid 48-bit command and produce the +-- following outputs: +-- 1. o_dataout -> a single bit output that produces the message to be sent to the +-- SD card one bit at a time. Every time the i_message_bit_out input +-- is high and the i_clock has a positive edge, a new bit is produced. +-- 2. o_message_done -> a signal that is asserted high when the entire message has been +-- produced through the o_dataout output. +-- 3. o_valid -> is a signal that is asserted high if the specified message is valid. +-- 4. o_response_type -> indicates the command response type. +-- 5. o_returning_ocr -> the response from the SD card will contain the OCR register +-- 6. o_returning_cid -> the response from the SD card will contain the CID register +-- 7. o_returning_rca -> the response from the SD card will contain the RCA register +-- 8. o_returning_csd -> the response from the SD card will contain the CSD register +-- 9. o_data_read -> asserted when the command being sent is a data read command. +-- 10. o_data_write -> asserted when the command being sent is a data write command. +-- 11. o_wait_cmd_busy -> is set high when the response to this command will be +-- followed by a busy signal. +-- +-- NOTES/REVISIONS: +------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Altera_UP_SD_Card_48_bit_Command_Generator is + generic ( + -- Basic commands + COMMAND_0_GO_IDLE : STD_LOGIC_VECTOR(5 downto 0) := "000000"; + COMMAND_2_ALL_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "000010"; + COMMAND_3_SEND_RCA : STD_LOGIC_VECTOR(5 downto 0) := "000011"; + COMMAND_4_SET_DSR : STD_LOGIC_VECTOR(5 downto 0) := "000100"; + COMMAND_6_SWITCH_FUNCTION : STD_LOGIC_VECTOR(5 downto 0) := "000110"; + COMMAND_7_SELECT_CARD : STD_LOGIC_VECTOR(5 downto 0) := "000111"; + COMMAND_9_SEND_CSD : STD_LOGIC_VECTOR(5 downto 0) := "001001"; + COMMAND_10_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "001010"; + COMMAND_12_STOP_TRANSMISSION : STD_LOGIC_VECTOR(5 downto 0) := "001100"; + COMMAND_13_SEND_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101"; + COMMAND_15_GO_INACTIVE : STD_LOGIC_VECTOR(5 downto 0) := "001111"; + -- Block oriented read/write/lock commands + COMMAND_16_SET_BLOCK_LENGTH : STD_LOGIC_VECTOR(5 downto 0) := "010000"; + -- Block oriented read commands + COMMAND_17_READ_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "010001"; + COMMAND_18_READ_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010010"; + -- Block oriented write commands + COMMAND_24_WRITE_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "011000"; + COMMAND_25_WRITE_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "011001"; + COMMAND_27_PROGRAM_CSD : STD_LOGIC_VECTOR(5 downto 0) := "011011"; + -- Block oriented write-protection commands + COMMAND_28_SET_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011100"; + COMMAND_29_CLEAR_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011101"; + COMMAND_30_SEND_PROTECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "011110"; + -- Erase commands + COMMAND_32_ERASE_BLOCK_START : STD_LOGIC_VECTOR(5 downto 0) := "100000"; + COMMAND_33_ERASE_BLOCK_END : STD_LOGIC_VECTOR(5 downto 0) := "100001"; + COMMAND_38_ERASE_SELECTED_GROUPS: STD_LOGIC_VECTOR(5 downto 0) := "100110"; + -- Block lock commands + COMMAND_42_LOCK_UNLOCK : STD_LOGIC_VECTOR(5 downto 0) := "101010"; + -- Command Type Settings + COMMAND_55_APP_CMD : STD_LOGIC_VECTOR(5 downto 0) := "110111"; + COMMAND_56_GEN_CMD : STD_LOGIC_VECTOR(5 downto 0) := "111000"; + -- Application Specific commands - must be preceeded with command 55. + ACOMMAND_6_SET_BUS_WIDTH : STD_LOGIC_VECTOR(5 downto 0) := "000110"; + ACOMMAND_13_SD_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101"; + ACOMMAND_22_SEND_NUM_WR_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010100"; + ACOMMAND_23_SET_BLK_ERASE_COUNT : STD_LOGIC_VECTOR(5 downto 0) := "010101"; + ACOMMAND_41_SEND_OP_CONDITION : STD_LOGIC_VECTOR(5 downto 0) := "101001"; + ACOMMAND_42_SET_CLR_CARD_DETECT : STD_LOGIC_VECTOR(5 downto 0) := "101010"; + ACOMMAND_51_SEND_SCR : STD_LOGIC_VECTOR(5 downto 0) := "110011"; + -- First custom_command + FIRST_NON_PREDEFINED_COMMAND : STD_LOGIC_VECTOR(3 downto 0) := "1010" + ); + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_message_bit_out : in std_logic; + i_command_ID : in std_logic_vector(5 downto 0); + i_argument : in std_logic_vector(31 downto 0); + i_predefined_message : in std_logic_vector(3 downto 0); + i_generate : in std_logic; + i_DSR : in std_logic_vector(15 downto 0); + i_OCR : in std_logic_vector(31 downto 0); + i_RCA : in std_logic_vector(15 downto 0); + o_dataout : out std_logic; + o_message_done : out std_logic; + o_valid : out std_logic; + o_returning_ocr : out std_logic; + o_returning_cid : out std_logic; + o_returning_rca : out std_logic; + o_returning_csd : out std_logic; + o_returning_status : out std_logic; + o_data_read : out std_logic; + o_data_write : out std_logic; + o_wait_cmd_busy : out std_logic; + o_last_cmd_was_55 : out std_logic; + o_response_type : out std_logic_vector(2 downto 0) + ); + +end entity; + +architecture rtl of Altera_UP_SD_Card_48_bit_Command_Generator is + + component Altera_UP_SD_CRC7_Generator + port + ( + i_clock : in std_logic; + i_enable : in std_logic; + i_reset_n : in std_logic; + i_shift : in std_logic; + i_datain : in std_logic; + o_dataout : out std_logic; + o_crcout : out std_logic_vector(6 downto 0) + ); + end component; + + -- Local wires + -- REGISTERED + signal counter : std_logic_vector(6 downto 0); + signal last_command_id : std_logic_vector(5 downto 0); + signal message_bits : std_logic_vector(39 downto 0); + signal last_command_sent_was_CMD55, valid : std_logic; + signal bit_to_send, sending_CRC, command_valid : std_logic; + signal returning_cid_reg, returning_rca_reg, returning_csd_reg, returning_dsr_reg, returning_ocr_reg, returning_status_reg : std_logic; + -- UNREGISTERED + signal temp_4_bits : std_logic_vector(3 downto 0); + signal message_done, CRC_generator_out, produce_next_bit : std_logic; + signal app_specific_valid, regular_command_valid : std_logic; + signal response_type, response_type_reg : std_logic_vector(2 downto 0); + signal cmd_argument : std_logic_vector(31 downto 0); +begin + -- This set of bits is necessary to allow the SD card to accept a VDD level for communication. + temp_4_bits <= "1111" when ((i_OCR(23) = '1') or (i_OCR(22) = '1') or (i_OCR(21) = '1') or (i_OCR(20) = '1')) else "0000"; + -- Generate the bits to be sent to the SD card. These bits must pass through the CRC generator + -- to produce error checking code. The error checking code will follow the message. The message terminates with + -- a logic '1'. Total message length is 48 bits. + message_data_generator: process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + message_bits <= (OTHERS => '0'); + else + if (rising_edge(i_clock)) then + if (i_generate = '1') then + -- Store type of a response. + response_type_reg <= response_type; + -- Generate a message. Please note that the predefined messages are used for initialization. + -- If executed in sequence, they will initialize the SD card to work correctly. Only once these + -- instructions are completed can the data transfer begin. + case (i_predefined_message) is + when "0000" => + -- Generate a predefined message - CMD0. + message_bits <= ("01" & COMMAND_0_GO_IDLE & "00000000000000000000000000000000"); + when "0001" => + -- Generate a predefined message - CMD55. + message_bits <= ("01" & COMMAND_55_APP_CMD & "0000000000000000" & "0000000000000000"); + when "0010" => + -- Generate a predefined message - ACMD41. + message_bits <= ("01" & ACOMMAND_41_SEND_OP_CONDITION & "0000" & temp_4_bits & "000" & i_OCR(20) & "00000000000000000000"); + when "0011" => + -- Generate a predefined message - CMD2. + message_bits <= ("01" & COMMAND_2_ALL_SEND_CID & "00000000000000000000000000000000"); + when "0100" => + -- Generate a predefined message - CMD3. + message_bits <= ("01" & COMMAND_3_SEND_RCA & "00000000000000000000000000000000"); + when "0101" => + -- Generate a predefined message - CMD9. + message_bits <= ("01" & COMMAND_9_SEND_CSD & i_RCA & "0000000000000000"); + when "0110" => + -- Generate a predefined message - CMD4. + message_bits <= ("01" & COMMAND_4_SET_DSR & i_DSR & "0000000000000000"); + when "0111" => + -- Generate a predefined message - CMD16. Set block length to 512. + message_bits <= ("01" & COMMAND_16_SET_BLOCK_LENGTH & "0000000000000000" & "0000001000000000" ); + when "1000" => + -- Generate a predefined message - CMD7. Select the card so we can access it's data. + message_bits <= ("01" & COMMAND_7_SELECT_CARD & i_RCA & "0000001000000000" ); + when "1001" => + -- Generate a predefined message - CMD13. Send SD card status. + message_bits <= ("01" & COMMAND_13_SEND_STATUS & i_RCA & "0000000000000000"); + + when others => + -- Generate a custom message + message_bits <= ("01" & i_command_ID & cmd_argument); + end case; + else + -- Shift bits out as needed + if (produce_next_bit = '1') then + -- Shift message bits. + message_bits(39 downto 1) <= message_bits(38 downto 0); + message_bits(0) <= '0'; + end if; + end if; + end if; + end if; + end process; + + -- Generate command argument based on the command_ID. For most commands, the argument is user specified. + -- For some commands, it is necessary to send a particular SD Card register contents. Hence, these contents are + -- sent instead of the user data. + argument_generator: process (i_command_ID, last_command_sent_was_CMD55, i_generate, i_RCA, i_DSR, i_OCR, i_argument) + begin + cmd_argument <= i_argument; + if (i_generate = '1') then + case (i_command_ID) is + when COMMAND_4_SET_DSR => + cmd_argument <= i_DSR & i_argument(15 downto 0); + when COMMAND_7_SELECT_CARD => + cmd_argument <= i_RCA & i_argument(15 downto 0); + when COMMAND_9_SEND_CSD => + cmd_argument <= i_RCA & i_argument(15 downto 0); + when COMMAND_10_SEND_CID => + cmd_argument <= i_RCA & i_argument(15 downto 0); + when COMMAND_13_SEND_STATUS => + cmd_argument <= i_RCA & i_argument(15 downto 0); + when COMMAND_15_GO_INACTIVE => + cmd_argument <= i_RCA & i_argument(15 downto 0); + when COMMAND_55_APP_CMD => + cmd_argument <= i_RCA & i_argument(15 downto 0); + when ACOMMAND_41_SEND_OP_CONDITION => + if (last_command_sent_was_CMD55 = '1') then + cmd_argument <= i_OCR; + end if; + when others => + cmd_argument <= i_argument; + end case; + end if; + end process; + + -- Validate the message ID before sending it out. + command_validator: process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + command_valid <= '0'; + else + if (rising_edge(i_clock)) then + if (i_generate = '1') then + if (("0" & i_predefined_message) >= ("0" & FIRST_NON_PREDEFINED_COMMAND)) then + -- Check the custom message + if (last_command_sent_was_CMD55 = '1') then + -- Check the application specific messages + command_valid <= app_specific_valid; + else + -- Check the default messages. + command_valid <= regular_command_valid; + end if; + else + -- A command is valid if the message is predefined. + command_valid <= '1'; + end if; + end if; + end if; + end if; + end process; + + -- Registers that indicate that the command sent will return contents of a control register. + -- The contents of the response should therefore be stored in the appropriate register. + responses_with_control_regs: process(i_clock, i_reset_n, last_command_sent_was_CMD55, last_command_id, message_done) + begin + if (i_reset_n = '0') then + returning_ocr_reg <= '0'; + returning_cid_reg <= '0'; + returning_rca_reg <= '0'; + returning_csd_reg <= '0'; + returning_status_reg <= '0'; + elsif (rising_edge(i_clock)) then + if (i_generate = '1') then + returning_ocr_reg <= '0'; + returning_cid_reg <= '0'; + returning_rca_reg <= '0'; + returning_csd_reg <= '0'; + returning_status_reg <= '0'; + elsif (message_done = '1') then + -- OCR + if ((last_command_sent_was_CMD55 = '1') and (last_command_id = ACOMMAND_41_SEND_OP_CONDITION)) then + returning_ocr_reg <= '1'; + end if; + -- CID + if (last_command_id = COMMAND_2_ALL_SEND_CID) then + returning_cid_reg <= '1'; + end if; + -- RCA + if (last_command_id = COMMAND_3_SEND_RCA) then + returning_rca_reg <= '1'; + end if; + -- CSD + if (last_command_id = COMMAND_9_SEND_CSD) then + returning_csd_reg <= '1'; + end if; + -- Status + if ((last_command_sent_was_CMD55 = '0') and (last_command_id = COMMAND_13_SEND_STATUS)) then + returning_status_reg <= '1'; + end if; + + end if; + end if; + end process; + + -- Count the number of bits sent using a counter. + sent_bit_counter: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter) + begin + if (i_reset_n = '0') then + counter <= (OTHERS => '0'); + else + if (rising_edge(i_clock)) then + if (i_generate = '1') then + -- Reset the counter indicating the number of bits produced. + counter <= "0000000"; + else + if (produce_next_bit = '1') then + -- Update the number of message bits sent. + counter <= counter + '1'; + end if; + end if; + end if; + end if; + end process; + + -- Select the source for the output data to be either the message data or the CRC bits. + source_selector: process(i_clock, i_reset_n, i_generate) + begin + if (i_reset_n = '0') then + sending_CRC <= '0'; + else + if (rising_edge(i_clock)) then + if (i_generate = '1') then + -- Set sending CRC flag to 0. + sending_CRC <= '0'; + else + -- If this is the last bit being sent, then bits that follow are the CRC bits. + if (counter = "0101000") then + sending_CRC <= '1'; + end if; + end if; + end if; + end if; + end process; + + -- When the message is sent, store its ID. In a special case when CMD55 is sent, the next command can be an application + -- specific command. We need to check those command IDs to verify the validity of the message. + CMD55_recognizer: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter, message_done, last_command_id) + begin + if (i_reset_n = '0') then + last_command_sent_was_CMD55 <= '0'; + else + if (rising_edge(i_clock)) then + if (i_generate = '0') then + -- Store the ID of the current command. + if (produce_next_bit = '1') then + if (counter = "0000000") then + last_command_id <= message_bits(37 downto 32); + end if; + end if; + -- When message has been sent then check if it was CMD55. + if (message_done = '1') then + if (last_command_id = COMMAND_55_APP_CMD) then + last_command_sent_was_CMD55 <= '1'; + else + last_command_sent_was_CMD55 <= '0'; + end if; + end if; + end if; + end if; + end if; + end process; + + -- Instantiate a CRC7 generator. Message bits will pass through it to create the CRC code for the message. + CRC7_Gen: Altera_UP_SD_CRC7_Generator PORT MAP + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_enable => i_message_bit_out, + i_shift => sending_CRC, + i_datain => message_bits(39), + o_dataout => CRC_generator_out + ); + + -- Define the source of the data produced by this module, depending on the counter value and the sending_CRC register state. + data_bit_register: process(i_clock, i_reset_n, i_generate, produce_next_bit, counter) + begin + if (i_reset_n = '0') then + bit_to_send <= '1'; + else + if (rising_edge(i_clock)) then + if (i_generate = '1') then + bit_to_send <= '1'; + elsif (produce_next_bit = '1') then + -- Send data to output. + if (sending_CRC = '0') then + -- Send message bits + bit_to_send <= message_bits(39); + else + -- Send CRC bits + if ((counter = "0101111") or (counter = "0110000")) then + -- At the end of CRC bits put a 1. + bit_to_send <= '1'; + else + bit_to_send <= CRC_generator_out; + end if; + end if; + end if; + end if; + end if; + end process; + + -- Define conditions to produce the next message bit on the module output port o_dataout. + produce_next_bit <= i_message_bit_out and (not message_done); + -- Message is done when the last bit appears at the output. + message_done <= '1' when (counter = "0110001") else '0'; + -- Check the application specific messages + app_specific_valid <= '1' when ( + --(i_command_ID = COMMAND_0_GO_IDLE) or + (i_command_ID = COMMAND_2_ALL_SEND_CID) or + (i_command_ID = COMMAND_3_SEND_RCA) or + (i_command_ID = COMMAND_4_SET_DSR) or + --(i_command_ID = ACOMMAND_6_SET_BUS_WIDTH) or + --(i_command_ID = COMMAND_7_SELECT_CARD) or + (i_command_ID = COMMAND_9_SEND_CSD) or + (i_command_ID = COMMAND_10_SEND_CID) or + --(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or + (i_command_ID = ACOMMAND_13_SD_STATUS) or + --(i_command_ID = COMMAND_15_GO_INACTIVE) or + --(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or + (i_command_ID = COMMAND_17_READ_BLOCK) or + --(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or + (i_command_ID = ACOMMAND_22_SEND_NUM_WR_BLOCKS) or + (i_command_ID = ACOMMAND_23_SET_BLK_ERASE_COUNT) or + (i_command_ID = COMMAND_24_WRITE_BLOCK) or + (i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or + (i_command_ID = COMMAND_27_PROGRAM_CSD) or + (i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or + (i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or + (i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or + (i_command_ID = COMMAND_32_ERASE_BLOCK_START) or + (i_command_ID = COMMAND_33_ERASE_BLOCK_END) or + (i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or + (i_command_ID = ACOMMAND_41_SEND_OP_CONDITION) or + (i_command_ID = ACOMMAND_42_SET_CLR_CARD_DETECT) or + (i_command_ID = ACOMMAND_51_SEND_SCR) or + (i_command_ID = COMMAND_55_APP_CMD) or + (i_command_ID = COMMAND_56_GEN_CMD) + ) + else '0'; + -- Check the default messages. + regular_command_valid <= '1' when ( + ------------------------------------------------------- + -- Disabled to prevent malfunction of the core + ------------------------------------------------------- + --(i_command_ID = COMMAND_0_GO_IDLE) or + --(i_command_ID = COMMAND_6_SWITCH_FUNCTION) or + --(i_command_ID = COMMAND_7_SELECT_CARD) or + --(i_command_ID = COMMAND_15_GO_INACTIVE) or + --(i_command_ID = COMMAND_27_PROGRAM_CSD) or + --(i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or + --(i_command_ID = COMMAND_42_LOCK_UNLOCK) or + ------------------------------------------------------- + (i_command_ID = COMMAND_2_ALL_SEND_CID) or + (i_command_ID = COMMAND_3_SEND_RCA) or + (i_command_ID = COMMAND_4_SET_DSR) or + (i_command_ID = COMMAND_9_SEND_CSD) or + (i_command_ID = COMMAND_10_SEND_CID) or + (i_command_ID = COMMAND_13_SEND_STATUS) or + ------------------------------------------------------- + -- Disabled to simplify the circuit + ------------------------------------------------------- + --(i_command_ID = COMMAND_12_STOP_TRANSMISSION) or + --(i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or + --(i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or + --(i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or + ------------------------------------------------------- + (i_command_ID = COMMAND_17_READ_BLOCK) or + (i_command_ID = COMMAND_24_WRITE_BLOCK) or + (i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or + (i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or + (i_command_ID = COMMAND_32_ERASE_BLOCK_START) or + (i_command_ID = COMMAND_33_ERASE_BLOCK_END) or + (i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or + (i_command_ID = COMMAND_55_APP_CMD) or + (i_command_ID = COMMAND_56_GEN_CMD) + ) + else '0'; + + response_type <= "001" when -- Wait for type 1 response when + ( + (i_predefined_message = "0001") or + (i_predefined_message = "0111") or + (i_predefined_message = "1000") or + (i_predefined_message = "1001") or + ((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and + ((i_command_ID = COMMAND_6_SWITCH_FUNCTION) or + (i_command_ID = COMMAND_7_SELECT_CARD) or + (i_command_ID = COMMAND_12_STOP_TRANSMISSION) or + (i_command_ID = COMMAND_13_SEND_STATUS) or + (i_command_ID = COMMAND_16_SET_BLOCK_LENGTH) or + (i_command_ID = COMMAND_17_READ_BLOCK) or + (i_command_ID = COMMAND_18_READ_MULTIPLE_BLOCKS) or + (i_command_ID = COMMAND_24_WRITE_BLOCK) or + (i_command_ID = COMMAND_25_WRITE_MULTIPLE_BLOCKS) or + (i_command_ID = COMMAND_27_PROGRAM_CSD) or + (i_command_ID = COMMAND_28_SET_WRITE_PROTECT) or + (i_command_ID = COMMAND_29_CLEAR_WRITE_PROTECT) or + (i_command_ID = COMMAND_30_SEND_PROTECTED_GROUPS) or + (i_command_ID = COMMAND_32_ERASE_BLOCK_START) or + (i_command_ID = COMMAND_33_ERASE_BLOCK_END) or + (i_command_ID = COMMAND_38_ERASE_SELECTED_GROUPS) or + (i_command_ID = COMMAND_42_LOCK_UNLOCK) or + (i_command_ID = COMMAND_55_APP_CMD) or + (i_command_ID = COMMAND_56_GEN_CMD) or + ((last_command_sent_was_CMD55 = '1') and + ((i_command_ID = ACOMMAND_6_SET_BUS_WIDTH) or + (i_command_ID = ACOMMAND_13_SD_STATUS) or + (i_command_ID = ACOMMAND_22_SEND_NUM_WR_BLOCKS) or + (i_command_ID = ACOMMAND_23_SET_BLK_ERASE_COUNT) or + (i_command_ID = ACOMMAND_42_SET_CLR_CARD_DETECT) or + (i_command_ID = ACOMMAND_51_SEND_SCR))))) + ) else + "010" when -- Wait for type 2 response when + ( + ((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and + ((i_command_ID = COMMAND_2_ALL_SEND_CID) or + (i_command_ID = COMMAND_9_SEND_CSD) or + (i_command_ID = COMMAND_10_SEND_CID))) or + (i_predefined_message = "0011") or + (i_predefined_message = "0101") + ) else + "011" when -- Wait for type 3 response when + ( + ((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and (last_command_sent_was_CMD55 = '1') and (i_command_ID = ACOMMAND_41_SEND_OP_CONDITION)) or + (i_predefined_message = "0010") + ) else + "110" when -- Wait for type 6 response when + (((i_predefined_message = FIRST_NON_PREDEFINED_COMMAND) and (i_command_ID = COMMAND_3_SEND_RCA)) or + (i_predefined_message = "0100")) + else "000"; -- Otherwise there is no response pending. + + -- Define circuit outputs + o_message_done <= message_done; + o_response_type <= response_type_reg; + o_valid <= command_valid; + o_dataout <= bit_to_send; + o_returning_ocr <= returning_ocr_reg; + o_returning_cid <= returning_cid_reg; + o_returning_rca <= returning_rca_reg; + o_returning_csd <= returning_csd_reg; + o_returning_status <= returning_status_reg; + o_data_read <= '1' when (last_command_id = COMMAND_17_READ_BLOCK) else '0'; + o_data_write <= '1' when (last_command_id = COMMAND_24_WRITE_BLOCK) else '0'; + o_last_cmd_was_55 <= last_command_sent_was_CMD55; + o_wait_cmd_busy <= '1' when ( + (last_command_id = COMMAND_7_SELECT_CARD) or + (last_command_id = COMMAND_12_STOP_TRANSMISSION) or + (last_command_id = COMMAND_28_SET_WRITE_PROTECT) or + (last_command_id = COMMAND_29_CLEAR_WRITE_PROTECT) or + (last_command_id = COMMAND_38_ERASE_SELECTED_GROUPS)) + else '0'; +end rtl; \ No newline at end of file diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd new file mode 100644 index 0000000..9900419 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Avalon_Interface.vhd @@ -0,0 +1,518 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +---------------------------------------------------------------------------------------------------------------- +-- This is an FSM that allows access to the SD Card IP core via the Avalon Interconnect. +-- +-- This module takes a range of addresses on the Avalon Interconnect. Specifically: +-- - 0x00000000 to 0x000001ff +-- word addressable buffer space. The data to be written to the SD card as well +-- as data read from the SD card can be accessed here. +-- +-- - 0x00000200 to 0x0000020f +-- 128-bit containing the Card Identification Number. The meaning of each bit is described in the +-- SD Card Physical Layer Specification Document. +-- +-- - 0x00000210 to 0x0000021f +-- 128-bit register containing Card Specific Data. The meaning of each bit is described in the +-- SD Card Physical Layer Specification Document. +-- +-- - 0x00000220 to 0x00000223 +-- 32-bit register containing Operating Conditions Register. The meaning of each bit is described +-- in the SD Card Physical Layer Specification Document. +-- +-- - 0x00000224 to 0x00000227 +-- 32-bit register containing the Status Register. The meaning of each bit is described +-- in the SD Card Physical Layer Specification Document. However, if the card is not connected or the +-- status register could not be read from the SD card, this register will contain invalid data. In such +-- a case, wait for a card to be connected by checking the Auxiliary Status Register (UP Core Specific), and +-- a command 13 (SEND_STATUS) to update the contents of this register when possible. If a card is connected then +-- the Auxiliary Status Register can be polled until such a time that Status Register is valid, as the SD Card +-- interface circuit updates the status register approximately every 0.1 of a second, and after every command +-- is executed. +-- +-- - 0x00000228 to 0x000000229 +-- 16-bit register containing the Relative Card Address. This address uniquely identifies a card +-- connected to the SD Card slot. +-- +-- - 0x0000022C to 0x00000022F +-- 32-bit register used to set the argument for a command to be sent to the SD Card. +-- +-- - 0x00000230 to 0x000000231 +-- 16-bit register used to send a command to an SD card. Once written, the interface will issue the +-- specified command. The meaning of each bit in this register is as follows: +-- - 0-5 - command index. This is a command index as per SD Card Physical Layer specification document. +-- - 6 - use most recent RCA. If this bit is set, the command argument will be replaced with the contents of +-- the Relative Card Address register, followed by 16 0s. For commands that require RCA to be sent as +-- an argument, this bit should be set and users will not need to specify RCA themselves. +-- - 7-15 - currently unused bits. They will be ignored. +-- NOTE: If a specified command is determined to be invalid, or the card is not connected to the SD Card socket, +-- then the SD Card interface circuit will not issue the command. +-- +-- - 0x00000234 to 0x00000235 +-- 16-bit register with Auxiliary Status Register. This is the Altera UP SD Card Interface status. The meaning of +-- the bits is as follows: +-- - 0 - last command valid - Set to '1' if the most recently user issued command was valid. +-- - 1 - card connected - Set to '1' if at present an SD card +-- - 2 - execution in progress - Set to '1' if the command recently issued is currently being executed. If true, +-- then the current state of SD Card registers should be ignored. +-- - 3 - status register valid - Set to '1' if the status register is valid. +-- - 4 - command timed out - Set to '1' if the last command timed out. +-- - 5 - crc failed - Set to '1' if the last command failed a CRC check. +-- - 6-15 - unused. +-- +-- - 0x00000238 to 0x0000023B +-- 32-bit register containing the 32-bit R1 response message. Use it to test validity of the response. This register +-- will not store the response to SEND_STATUS command. Insteand, read the SD_status register at location 0x00000224. +-- +-- Date: December 8, 2008 +-- NOTES/REVISIONS: +-- December 17, 2008 - added R1 response register to the core. It is now available at 0x00000238. +---------------------------------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Altera_UP_SD_Card_Avalon_Interface is + generic ( + ADDRESS_BUFFER : std_logic_vector(7 downto 0) := "00000000"; + ADDRESS_CID : std_logic_vector(7 downto 0) := "10000000"; + ADDRESS_CSD : std_logic_vector(7 downto 0) := "10000100"; + ADDRESS_OCR : std_logic_vector(7 downto 0) := "10001000"; + ADDRESS_SR : std_logic_vector(7 downto 0) := "10001001"; + ADDRESS_RCA : std_logic_vector(7 downto 0) := "10001010"; + ADDRESS_ARGUMENT : std_logic_vector(7 downto 0) := "10001011"; + ADDRESS_COMMAND : std_logic_vector(7 downto 0) := "10001100"; + ADDRESS_ASR : std_logic_vector(7 downto 0) := "10001101"; + ADDRESS_R1 : std_logic_vector(7 downto 0) := "10001110" + ); + port + ( + -- Clock and Reset signals + i_clock : in STD_LOGIC; + i_reset_n : in STD_LOGIC; -- Asynchronous reset + + -- Avalon Interconnect Signals + i_avalon_address : in STD_LOGIC_VECTOR(7 downto 0); + i_avalon_chip_select : in STD_LOGIC; + i_avalon_read : in STD_LOGIC; + i_avalon_write : in STD_LOGIC; + i_avalon_byteenable : in STD_LOGIC_VECTOR(3 downto 0); + i_avalon_writedata : in STD_LOGIC_VECTOR(31 downto 0); + o_avalon_readdata : out STD_LOGIC_VECTOR(31 downto 0); + o_avalon_waitrequest : out STD_LOGIC; + + -- SD Card interface ports + b_SD_cmd : inout STD_LOGIC; + b_SD_dat : inout STD_LOGIC; + b_SD_dat3 : inout STD_LOGIC; + o_SD_clock : out STD_LOGIC + ); + +end entity; + +architecture rtl of Altera_UP_SD_Card_Avalon_Interface is + + component Altera_UP_SD_Card_Interface is + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + + -- Command interface + b_SD_cmd : inout std_logic; + b_SD_dat : inout std_logic; + b_SD_dat3 : inout std_logic; + i_command_ID : in std_logic_vector(5 downto 0); + i_argument : in std_logic_vector(31 downto 0); + i_user_command_ready : in std_logic; + + o_SD_clock : out std_logic; + o_card_connected : out std_logic; + o_command_completed : out std_logic; + o_command_valid : out std_logic; + o_command_timed_out : out std_logic; + o_command_crc_failed : out std_logic; + + -- Buffer access + i_buffer_enable : in std_logic; + i_buffer_address : in std_logic_vector(7 downto 0); + i_buffer_write : in std_logic; + i_buffer_data_in : in std_logic_vector(15 downto 0); + o_buffer_data_out : out std_logic_vector(15 downto 0); + + -- Show SD Card registers as outputs + o_SD_REG_card_identification_number : out std_logic_vector(127 downto 0); + o_SD_REG_relative_card_address : out std_logic_vector(15 downto 0); + o_SD_REG_operating_conditions_register : out std_logic_vector(31 downto 0); + o_SD_REG_card_specific_data : out std_logic_vector(127 downto 0); + o_SD_REG_status_register : out std_logic_vector(31 downto 0); + o_SD_REG_response_R1 : out std_logic_vector(31 downto 0); + o_SD_REG_status_register_valid : out std_logic + ); + end component; + + -- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state + -- of the switches. + type buffer_state_type is ( s_RESET, s_WAIT_REQUEST, s_READ_FIRST_WORD, s_READ_SECOND_WORD, s_RECEIVE_FIRST_WORD, + s_RECEIVE_SECOND_WORD, s_WR_READ_FIRST_WORD, s_WR_READ_FIRST_WORD_DELAY, s_WRITE_FIRST_BYTE, s_WRITE_FIRST_WORD, + s_WR_READ_SECOND_WORD, s_WR_READ_SECOND_WORD_DELAY, s_WRITE_SECOND_BYTE, s_WRITE_SECOND_WORD, s_WAIT_RELEASE); + type command_state_type is (s_RESET_CMD, s_WAIT_COMMAND, s_WAIT_RESPONSE, s_UPDATE_AUX_SR); + + -- Register to hold the current state + signal current_state : buffer_state_type; + signal next_state : buffer_state_type; + signal current_cmd_state : command_state_type; + signal next_cmd_state : command_state_type; + + ------------------- + -- Local signals + ------------------- + -- REGISTERED + signal auxiliary_status_reg : std_logic_vector(5 downto 0); + signal buffer_data_out_reg : std_logic_vector(31 downto 0); + signal buffer_data_in_reg : std_logic_vector(31 downto 0); + signal buffer_data_out : std_logic_vector(15 downto 0); + signal command_ID_reg : std_logic_vector( 5 downto 0); + signal argument_reg : std_logic_vector(31 downto 0); + signal avalon_address : std_logic_vector(7 downto 0); + signal avalon_byteenable : std_logic_vector(3 downto 0); + -- UNREGISTERED + signal buffer_address : std_logic_vector(7 downto 0); + signal buffer_data_in : std_logic_vector(15 downto 0); + signal SD_REG_card_identification_number : std_logic_vector(127 downto 0); + signal SD_REG_relative_card_address : std_logic_vector(15 downto 0); + signal SD_REG_operating_conditions_register : std_logic_vector(31 downto 0); + signal SD_REG_card_specific_data : std_logic_vector(127 downto 0); + signal SD_REG_status_register : std_logic_vector(31 downto 0); + signal SD_REG_response_R1 : std_logic_vector(31 downto 0); + signal command_ready, send_command_ready, + command_valid, command_completed, card_connected : std_logic; + signal status_reg_valid, argument_write : std_logic; + signal read_buffer_request, write_buffer_request, buffer_enable, buffer_write : std_logic; + signal command_timed_out, command_crc_failed : std_logic; + +begin + -- Define state transitions for buffer interface. + state_transitions_buffer: process (current_state, read_buffer_request, write_buffer_request, i_avalon_byteenable, avalon_byteenable) + begin + case current_state is + when s_RESET => + -- Reset local registers. + next_state <= s_WAIT_REQUEST; + + when s_WAIT_REQUEST => + -- Wait for a user command. + if (read_buffer_request = '1') then + next_state <= s_READ_FIRST_WORD; + elsif (write_buffer_request = '1') then + if ((i_avalon_byteenable(1) = '1') and (i_avalon_byteenable(0) = '1')) then + next_state <= s_WRITE_FIRST_WORD; + elsif ((i_avalon_byteenable(3) = '1') and (i_avalon_byteenable(2) = '1')) then + next_state <= s_WRITE_SECOND_WORD; + elsif ((i_avalon_byteenable(1) = '1') or (i_avalon_byteenable(0) = '1')) then + next_state <= s_WR_READ_FIRST_WORD; + elsif ((i_avalon_byteenable(3) = '1') or (i_avalon_byteenable(2) = '1')) then + next_state <= s_WR_READ_SECOND_WORD; + else + next_state <= s_WAIT_REQUEST; + end if; + else + next_state <= s_WAIT_REQUEST; + end if; + + when s_READ_FIRST_WORD => + -- Read first 16-bit word from the buffer + next_state <= s_READ_SECOND_WORD; + + when s_READ_SECOND_WORD => + -- Read second 16-bit word from the buffer + next_state <= s_RECEIVE_FIRST_WORD; + + when s_RECEIVE_FIRST_WORD => + -- Store first word read + next_state <= s_RECEIVE_SECOND_WORD; + + when s_RECEIVE_SECOND_WORD => + -- Store second word read + next_state <= s_WAIT_RELEASE; + + -- The following states control writing to the buffer. To write a single byte it is necessary to read a + -- word and then write it back, changing only on of its bytes. + when s_WR_READ_FIRST_WORD => + -- Read first 16-bit word from the buffer + next_state <= s_WR_READ_FIRST_WORD_DELAY; + + when s_WR_READ_FIRST_WORD_DELAY => + -- Wait a cycle + next_state <= s_WRITE_FIRST_BYTE; + + when s_WRITE_FIRST_BYTE => + -- Write one of the bytes in the given word into the memory. + if ((avalon_byteenable(3) = '1') and (avalon_byteenable(2) = '1')) then + next_state <= s_WRITE_SECOND_WORD; + elsif ((avalon_byteenable(3) = '1') or (avalon_byteenable(2) = '1')) then + next_state <= s_WR_READ_SECOND_WORD; + else + next_state <= s_WAIT_RELEASE; + end if; + + when s_WR_READ_SECOND_WORD => + -- Read second 16-bit word from the buffer + next_state <= s_WR_READ_SECOND_WORD_DELAY; + + when s_WR_READ_SECOND_WORD_DELAY => + -- Wait a cycle + next_state <= s_WRITE_SECOND_BYTE; + + when s_WRITE_SECOND_BYTE => + -- Write one of the bytes in the given word into the memory. + next_state <= s_WAIT_RELEASE; + + -- Full word writing can be done without reading the word in the first place. + when s_WRITE_FIRST_WORD => + -- Write the first word into memory + if ((avalon_byteenable(3) = '1') and (avalon_byteenable(2) = '1')) then + next_state <= s_WRITE_SECOND_WORD; + elsif ((avalon_byteenable(3) = '1') or (avalon_byteenable(2) = '1')) then + next_state <= s_WR_READ_SECOND_WORD; + else + next_state <= s_WAIT_RELEASE; + end if; + + when s_WRITE_SECOND_WORD => + -- Write the second word into memory + next_state <= s_WAIT_RELEASE; + + when s_WAIT_RELEASE => + -- if ((read_buffer_request = '1') or (write_buffer_request = '1')) then + -- next_state <= s_WAIT_RELEASE; + -- else + next_state <= s_WAIT_REQUEST; + -- end if; + + when others => + -- Make sure to start in the reset state if the circuit powers up in an odd state. + next_state <= s_RESET; + end case; + end process; + + -- State Registers + buffer_state_regs: process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + current_state <= s_RESET; + elsif(rising_edge(i_clock)) then + current_state <= next_state; + end if; + end process; + + helper_regs: process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + avalon_address <= (OTHERS => '0'); + buffer_data_out_reg <= (OTHERS => '0'); + buffer_data_in_reg <= (OTHERS => '0'); + avalon_byteenable <= (OTHERS => '0'); + elsif(rising_edge(i_clock)) then + if (current_state = s_WAIT_REQUEST) then + avalon_address <= i_avalon_address; + buffer_data_in_reg <= i_avalon_writedata; + avalon_byteenable <= i_avalon_byteenable; + end if; + if (current_state = s_RECEIVE_FIRST_WORD) then + buffer_data_out_reg(15 downto 0) <= buffer_data_out; + end if; + if (current_state = s_RECEIVE_SECOND_WORD) then + buffer_data_out_reg(31 downto 16) <= buffer_data_out; + end if; + end if; + end process; + + -- FSM outputs + o_avalon_waitrequest <= (read_buffer_request or write_buffer_request) when (not (current_state = s_WAIT_RELEASE)) else '0'; + buffer_address(7 downto 1) <= avalon_address(6 downto 0); + buffer_address(0) <= '1' when ( (current_state = s_READ_SECOND_WORD) or (current_state = s_WRITE_SECOND_WORD) or + (current_state = s_WR_READ_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else + '0'; + buffer_enable <= '1' when ( (current_state = s_READ_FIRST_WORD) or (current_state = s_WR_READ_FIRST_WORD) or + (current_state = s_READ_SECOND_WORD) or (current_state = s_WR_READ_SECOND_WORD) or + (current_state = s_WRITE_FIRST_WORD) or (current_state = s_WRITE_FIRST_BYTE) or + (current_state = s_WRITE_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else + '0'; + buffer_write <= '1' when ( (current_state = s_WRITE_FIRST_WORD) or (current_state = s_WRITE_FIRST_BYTE) or + (current_state = s_WRITE_SECOND_WORD) or (current_state = s_WRITE_SECOND_BYTE)) else + '0'; + buffer_data_in <= (buffer_data_out(15 downto 8) & buffer_data_in_reg(7 downto 0)) when ((current_state = s_WRITE_FIRST_BYTE) and (avalon_byteenable(1 downto 0) = "01")) else + (buffer_data_in_reg(15 downto 8) & buffer_data_out(7 downto 0)) when ((current_state = s_WRITE_FIRST_BYTE) and (avalon_byteenable(1 downto 0) = "10")) else + (buffer_data_out(15 downto 8) & buffer_data_in_reg(23 downto 16)) when ((current_state = s_WRITE_SECOND_BYTE) and (avalon_byteenable(3 downto 2) = "01")) else + (buffer_data_in_reg(31 downto 24) & buffer_data_out(7 downto 0)) when ((current_state = s_WRITE_SECOND_BYTE) and (avalon_byteenable(3 downto 2) = "10")) else + buffer_data_in_reg(15 downto 0) when (current_state = s_WRITE_FIRST_WORD) else + buffer_data_in_reg(31 downto 16); + -- Glue Logic + read_buffer_request <= (not i_avalon_address(7)) and (i_avalon_chip_select) and (i_avalon_read); + write_buffer_request <= (not i_avalon_address(7)) and (i_avalon_chip_select) and (i_avalon_write); + + -- Define state transitions for command interface. + state_transitions_cmd: process (current_cmd_state, command_completed, command_valid, command_ready) + begin + case current_cmd_state is + when s_RESET_CMD => + -- Reset local registers. + next_cmd_state <= s_WAIT_COMMAND; + + when s_WAIT_COMMAND => + -- Wait for a user command. + if (command_ready = '1') then + next_cmd_state <= s_WAIT_RESPONSE; + else + next_cmd_state <= s_WAIT_COMMAND; + end if; + + when s_WAIT_RESPONSE => + -- Generate a predefined command to the SD card. This is the identification process for the SD card. + if ((command_completed = '1') or (command_valid = '0')) then + next_cmd_state <= s_UPDATE_AUX_SR; + else + next_cmd_state <= s_WAIT_RESPONSE; + end if; + + when s_UPDATE_AUX_SR => + -- Update the Auxiliary status register. + if (command_ready = '1') then + next_cmd_state <= s_UPDATE_AUX_SR; + else + next_cmd_state <= s_WAIT_COMMAND; + end if; + + when others => + -- Make sure to start in the reset state if the circuit powers up in an odd state. + next_cmd_state <= s_RESET_CMD; + end case; + end process; + + -- State registers + cmd_state_regs: process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + current_cmd_state <= s_RESET_CMD; + elsif(rising_edge(i_clock)) then + current_cmd_state <= next_cmd_state; + end if; + end process; + + -- FSM outputs + send_command_ready <= '1' when ((current_cmd_state = s_WAIT_RESPONSE) or (current_cmd_state = s_UPDATE_AUX_SR)) else '0'; + + -- Glue logic + command_ready <= '1' when ( (i_avalon_chip_select = '1') and (i_avalon_write = '1') and + (i_avalon_address = ADDRESS_COMMAND)) else '0'; + argument_write <= '1' when ((i_avalon_chip_select = '1') and (i_avalon_write = '1') and + (i_avalon_address = ADDRESS_ARGUMENT)) else '0'; + -- Local Registers + local_regs: process(i_clock, i_reset_n, current_cmd_state, card_connected, command_valid, i_avalon_writedata, command_completed, command_ready) + begin + if (i_reset_n = '0') then + auxiliary_status_reg <= "000000"; + command_ID_reg <= (OTHERS => '0'); + elsif(rising_edge(i_clock)) then + -- AUX Status Register + if ((current_cmd_state = s_WAIT_RESPONSE) or (current_cmd_state = s_UPDATE_AUX_SR)) then + auxiliary_status_reg(2) <= not command_completed; + auxiliary_status_reg(4) <= command_timed_out; + auxiliary_status_reg(5) <= command_crc_failed; + end if; + auxiliary_status_reg(0) <= command_valid; + auxiliary_status_reg(1) <= card_connected; + auxiliary_status_reg(3) <= status_reg_valid; + -- Command + if (command_ready = '1') then + command_ID_reg <= i_avalon_writedata(5 downto 0); + end if; + end if; + end process; + + argument_regs_processing: process(i_clock, i_reset_n, current_cmd_state, i_avalon_writedata, command_ready) + begin + if (i_reset_n = '0') then + argument_reg <= (OTHERS => '0'); + elsif(rising_edge(i_clock)) then + -- Argument register + if ((command_ready = '1') and ( i_avalon_writedata(6) = '1')) then + argument_reg <= SD_REG_relative_card_address & "0000000000000000"; + elsif (argument_write = '1') then + argument_reg <= i_avalon_writedata; + end if; + end if; + end process; + + o_avalon_readdata <= buffer_data_out_reg when (not (current_state = s_WAIT_REQUEST)) else + SD_REG_card_identification_number(31 downto 0) when (i_avalon_address = ADDRESS_CID) else + SD_REG_card_identification_number(63 downto 32) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "01") else + SD_REG_card_identification_number(95 downto 64) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "10") else + SD_REG_card_identification_number(127 downto 96) when (i_avalon_address = ADDRESS_CID(7 downto 2) & "11") else + SD_REG_card_specific_data(31 downto 0) when (i_avalon_address = ADDRESS_CSD) else + SD_REG_card_specific_data(63 downto 32) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "01") else + SD_REG_card_specific_data(95 downto 64) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "10") else + SD_REG_card_specific_data(127 downto 96) when (i_avalon_address = ADDRESS_CSD(7 downto 2) & "11") else + SD_REG_operating_conditions_register when (i_avalon_address = ADDRESS_OCR) else + SD_REG_status_register when (i_avalon_address = ADDRESS_SR) else + ("0000000000000000" & SD_REG_relative_card_address)when (i_avalon_address = ADDRESS_RCA) else + argument_reg when (i_avalon_address = ADDRESS_ARGUMENT) else + ("00000000000000000000000000" & command_ID_reg) when (i_avalon_address = ADDRESS_COMMAND) else + SD_REG_response_R1 when (i_avalon_address = ADDRESS_R1) else + ("00000000000000000000000000" & auxiliary_status_reg); + + -- Instantiated Components + SD_Card_Port: Altera_UP_SD_Card_Interface + port map + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + + -- Command interface + b_SD_cmd => b_SD_cmd, + b_SD_dat => b_SD_dat, + b_SD_dat3 => b_SD_dat3, + i_command_ID => command_ID_reg, + i_argument => argument_reg, + i_user_command_ready => send_command_ready, + + o_SD_clock => o_SD_clock, + o_card_connected => card_connected, + o_command_completed => command_completed, + o_command_valid => command_valid, + o_command_timed_out => command_timed_out, + o_command_crc_failed => command_crc_failed, + + -- Buffer access + i_buffer_enable => buffer_enable, + i_buffer_address => buffer_address, + i_buffer_write => buffer_write, + i_buffer_data_in => buffer_data_in, + o_buffer_data_out => buffer_data_out, + + -- Show SD Card registers as outputs + o_SD_REG_card_identification_number => SD_REG_card_identification_number, + o_SD_REG_relative_card_address => SD_REG_relative_card_address, + o_SD_REG_operating_conditions_register => SD_REG_operating_conditions_register, + o_SD_REG_card_specific_data => SD_REG_card_specific_data, + o_SD_REG_status_register => SD_REG_status_register, + o_SD_REG_response_R1 => SD_REG_response_R1, + o_SD_REG_status_register_valid => status_reg_valid + ); + +end rtl; + diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd new file mode 100644 index 0000000..3cdb04f --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Buffer.vhd @@ -0,0 +1,382 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +------------------------------------------------------------------------------------- +-- This module is a dual port memory block. It has a 16-bit port and a 1-bit port. +-- The 1-bit port is used to either send or receive data, while the 16-bit port is used +-- by Avalon interconnet to store and retrieve data. +-- +-- NOTES/REVISIONS: +------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Altera_UP_SD_Card_Buffer is + generic ( + TIMEOUT : std_logic_vector(15 downto 0) := "1111111111111111"; + BUSY_WAIT : std_logic_vector(15 downto 0) := "0000001111110000" + ); + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + + -- 1 bit port to transmit and receive data on the data line. + i_begin : in std_logic; + i_sd_clock_pulse_trigger : in std_logic; + i_transmit : in std_logic; + i_1bit_data_in : in std_logic; + o_1bit_data_out : out std_logic; + o_operation_complete : out std_logic; + o_crc_passed : out std_logic; + o_timed_out : out std_logic; + o_dat_direction : out std_logic; -- set to 1 to send data, set to 0 to receive it. + + -- 16 bit port to be accessed by a user circuit. + i_enable_16bit_port : in std_logic; + i_address_16bit_port : in std_logic_vector(7 downto 0); + i_write_16bit : in std_logic; + i_16bit_data_in : in std_logic_vector(15 downto 0); + o_16bit_data_out : out std_logic_vector(15 downto 0) + ); + +end entity; + +architecture rtl of Altera_UP_SD_Card_Buffer is + + component Altera_UP_SD_CRC16_Generator + port + ( + i_clock : in std_logic; + i_enable : in std_logic; + i_reset_n : in std_logic; + i_sync_reset : in std_logic; + i_shift : in std_logic; + i_datain : in std_logic; + o_dataout : out std_logic; + o_crcout : out std_logic_vector(15 downto 0) + ); + end component; + + component Altera_UP_SD_Card_Memory_Block + PORT + ( + address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + enable_a : IN STD_LOGIC := '1'; + enable_b : IN STD_LOGIC := '1'; + wren_a : IN STD_LOGIC := '1'; + wren_b : IN STD_LOGIC := '1'; + q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0) + ); + END component; + + -- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state + -- of the switches. + type state_type is (s_RESET, s_WAIT_REQUEST, s_SEND_START_BIT, s_SEND_DATA, s_SEND_CRC, s_SEND_STOP, s_WAIT_BUSY, s_WAIT_BUSY_END, + s_WAIT_DATA_START, s_RECEIVING_LEADING_BITS, s_RECEIVING_DATA, s_RECEIVING_STOP_BIT, s_WAIT_DEASSERT); + + -- Register to hold the current state + signal current_state : state_type; + signal next_state : state_type; + -- Local wires + -- REGISTERED + signal crc_counter : std_logic_vector(3 downto 0); + signal local_mode : std_logic; + signal dataout_1bit : std_logic; + signal bit_counter : std_logic_vector(2 downto 0); + signal byte_counter : std_logic_vector(8 downto 0); + signal shift_register : std_logic_vector(16 downto 0); + signal timeout_register : std_logic_vector(15 downto 0); + signal data_in_reg : std_logic; + -- UNREGISTERED + signal crc_out : std_logic_vector(15 downto 0); + signal single_bit_conversion, single_bit_out : std_logic_vector( 0 downto 0); + signal packet_mem_addr_b : std_logic_vector(11 downto 0); + signal local_reset, to_crc_generator, from_crc_generator, from_mem_1_bit, shift_crc, + recv_data, crc_generator_enable : std_logic; +begin + -- State transitions + state_transitions: process( current_state, i_begin, i_sd_clock_pulse_trigger, i_transmit, byte_counter, + bit_counter, crc_counter, i_1bit_data_in, timeout_register, data_in_reg) + begin + case (current_state) is + when s_RESET => + -- Reset local registers and begin waiting for user input. + next_state <= s_WAIT_REQUEST; + + when s_WAIT_REQUEST => + -- Wait for i_begin to be high + if ((i_begin = '1') and (i_sd_clock_pulse_trigger = '1')) then + if (i_transmit = '1') then + next_state <= s_SEND_START_BIT; + else + next_state <= s_WAIT_DATA_START; + end if; + else + next_state <= s_WAIT_REQUEST; + end if; + + when s_SEND_START_BIT => + -- Send a 0 first, followed by 4096 bits of data, 16 CRC bits, and stop bit. + if (i_sd_clock_pulse_trigger = '1') then + next_state <= s_SEND_DATA; + else + next_state <= s_SEND_START_BIT; + end if; + + when s_SEND_DATA => + -- Send 4096 data bits + if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then + next_state <= s_SEND_CRC; + else + next_state <= s_SEND_DATA; + end if; + + when s_SEND_CRC => + -- Send 16 CRC bits + if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then + next_state <= s_SEND_STOP; + else + next_state <= s_SEND_CRC; + end if; + + when s_SEND_STOP => + -- Send stop bit. + if (i_sd_clock_pulse_trigger = '1') then + next_state <= s_WAIT_BUSY; + else + next_state <= s_SEND_STOP; + end if; + + when s_WAIT_BUSY => + -- After a write, wait for the busy signal. Do not return a done signal until you receive a busy signal. + -- If you do not and a long time expires, then the data must have been rejected (due to CRC error maybe). + -- In such a case return failure. + if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0') and (timeout_register = "0000000000010000")) then + next_state <= s_WAIT_BUSY_END; + else + if (timeout_register = BUSY_WAIT) then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_WAIT_BUSY; + end if; + end if; + + when s_WAIT_BUSY_END => + if (i_sd_clock_pulse_trigger = '1') then + if (data_in_reg = '1') then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_WAIT_BUSY_END; + end if; + else + next_state <= s_WAIT_BUSY_END; + end if; + + when s_WAIT_DATA_START => + -- Wait for the start bit + if ((i_sd_clock_pulse_trigger = '1') and (data_in_reg = '0')) then + next_state <= s_RECEIVING_LEADING_BITS; + else + if (timeout_register = TIMEOUT) then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_WAIT_DATA_START; + end if; + end if; + + when s_RECEIVING_LEADING_BITS => + -- shift the start bit in as well as the next 16 bits. Once they are all in you can start putting data into memory. + if ((i_sd_clock_pulse_trigger = '1') and (crc_counter = "1111")) then + next_state <= s_RECEIVING_DATA; + else + next_state <= s_RECEIVING_LEADING_BITS; + end if; + + when s_RECEIVING_DATA => + -- Wait until all bits arrive. + if ((i_sd_clock_pulse_trigger = '1') and (bit_counter = "000") and (byte_counter = "111111111")) then + next_state <= s_RECEIVING_STOP_BIT; + else + next_state <= s_RECEIVING_DATA; + end if; + + when s_RECEIVING_STOP_BIT => + -- Wait until all bits arrive. + if (i_sd_clock_pulse_trigger = '1')then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_RECEIVING_STOP_BIT; + end if; + + when s_WAIT_DEASSERT => + if (i_begin = '1') then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_WAIT_REQUEST; + end if; + + when others => + next_state <= s_RESET; + end case; + end process; + + -- State registers + state_regs: process(i_clock, i_reset_n, local_reset) + begin + if (i_reset_n = '0') then + current_state <= s_RESET; + elsif (rising_edge(i_clock)) then + current_state <= next_state; + end if; + end process; + + -- FSM outputs + to_crc_generator <= shift_register(16) when (current_state = s_RECEIVING_DATA) else + from_mem_1_bit when (current_state = s_SEND_DATA) else + '0'; + shift_crc <= '1' when (current_state = s_SEND_CRC) else '0'; + local_reset <= '1' when ((current_state = s_RESET) or (current_state = s_WAIT_REQUEST)) else '0'; + recv_data <= '1' when (current_state = s_RECEIVING_DATA) else '0'; + single_bit_conversion(0) <= shift_register(15); + crc_generator_enable <= '0' when (current_state = s_WAIT_DEASSERT) else i_sd_clock_pulse_trigger; + o_operation_complete <= '1' when (current_state = s_WAIT_DEASSERT) else '0'; + o_dat_direction <= '1' when ( (current_state = s_SEND_START_BIT) or + (current_state = s_SEND_DATA) or + (current_state = s_SEND_CRC) or + (current_state = s_SEND_STOP)) + else '0'; + o_1bit_data_out <= dataout_1bit; + o_crc_passed <= '1' when ((crc_out = shift_register(16 downto 1)) and (shift_register(0) = '1')) else '0'; + o_timed_out <= '1' when (timeout_register = TIMEOUT) else '0'; + + -- Local components + local_regs: process(i_clock, i_reset_n, local_reset) + begin + if (i_reset_n = '0') then + bit_counter <= (OTHERS => '1'); + byte_counter <= (OTHERS => '0'); + dataout_1bit <= '1'; + crc_counter <= (OTHERS => '0'); + shift_register <= (OTHERS => '0'); + elsif (rising_edge(i_clock)) then + -- counters and serial output + if (local_reset = '1') then + bit_counter <= (OTHERS => '1'); + byte_counter <= (OTHERS => '0'); + dataout_1bit <= '1'; + data_in_reg <= '1'; + crc_counter <= (OTHERS => '0'); + shift_register <= (OTHERS => '0'); + elsif (i_sd_clock_pulse_trigger = '1') then + if ((not (current_state = s_RECEIVING_LEADING_BITS)) and (not (current_state = s_SEND_CRC))) then + crc_counter <= (OTHERS => '0'); + else + if (not (crc_counter = "1111")) then + crc_counter <= crc_counter + '1'; + end if; + end if; + if ((current_state = s_RECEIVING_DATA) or (current_state = s_SEND_DATA)) then + if (not ((bit_counter = "000") and (byte_counter = "111111111"))) then + if (bit_counter = "000") then + byte_counter <= byte_counter + '1'; + bit_counter <= "111"; + else + bit_counter <= bit_counter - '1'; + end if; + end if; + end if; + -- Output data bit. + if (current_state = s_SEND_START_BIT) then + dataout_1bit <= '0'; + elsif (current_state = s_SEND_DATA) then + dataout_1bit <= from_mem_1_bit; + elsif (current_state = s_SEND_CRC) then + dataout_1bit <= from_crc_generator; + else + dataout_1bit <= '1'; -- Stop bit. + end if; + + -- Shift register to store the CRC bits once the message is received. + if ((current_state = s_RECEIVING_DATA) or + (current_state = s_RECEIVING_LEADING_BITS) or + (current_state = s_RECEIVING_STOP_BIT)) then + shift_register(16 downto 1) <= shift_register(15 downto 0); + shift_register(0) <= data_in_reg; + end if; + data_in_reg <= i_1bit_data_in; + end if; + end if; + end process; + + -- Register holding the timeout value for data transmission. + timeout_reg: process(i_clock, i_reset_n, current_state, i_sd_clock_pulse_trigger) + begin + if (i_reset_n = '0') then + timeout_register <= (OTHERS => '0'); + elsif (rising_edge(i_clock)) then + if ((current_state = s_SEND_STOP) or + (current_state = s_WAIT_REQUEST)) then + timeout_register <= (OTHERS => '0'); + elsif (i_sd_clock_pulse_trigger = '1') then + -- Increment the timeout counter + if (((current_state = s_WAIT_DATA_START) or + (current_state = s_WAIT_BUSY)) and (not (timeout_register = TIMEOUT))) then + timeout_register <= timeout_register + '1'; + end if; + end if; + end if; + end process; + + -- Instantiated components. + crc16_checker: Altera_UP_SD_CRC16_Generator + port map + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_sync_reset => local_reset, + i_enable => crc_generator_enable, + i_shift => shift_crc, + i_datain => to_crc_generator, + o_dataout => from_crc_generator, + o_crcout => crc_out + ); + + packet_memory: Altera_UP_SD_Card_Memory_Block + PORT MAP + ( + address_a => i_address_16bit_port, + address_b => packet_mem_addr_b, + clock_a => i_clock, + clock_b => i_clock, + data_a => i_16bit_data_in, + data_b => single_bit_conversion, + enable_a => i_enable_16bit_port, + enable_b => '1', + wren_a => i_write_16bit, + wren_b => recv_data, + q_a => o_16bit_data_out, + q_b => single_bit_out + ); + from_mem_1_bit <= single_bit_out(0); + packet_mem_addr_b <= (byte_counter & bit_counter); + +end rtl; diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd new file mode 100644 index 0000000..094d9dd --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Clock.vhd @@ -0,0 +1,80 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +------------------------------------------------------------------------------------- +-- This module is a clock generator for the SD card interface. It takes a 50 MHz +-- clock as input and produces a clock signal that depends on the mode in which the +-- SD card interface is in. For a card identification mode a clock with a frequency of +-- 390.625 kHz is generated. For the data transfer mode, a clock with a frequency of +-- 12.5MHz is generated. +-- +-- In addition, the generator produces a clock_mode value that identifies the frequency +-- of the o_SD_clock that is currently being generated. +-- +-- NOTES/REVISIONS: +------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Altera_UP_SD_Card_Clock is + + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_enable : in std_logic; + i_mode : in std_logic; -- 0 for card identification mode, 1 for data transfer mode. + o_SD_clock : out std_logic; + o_clock_mode : out std_logic; + o_trigger_receive : out std_logic; + o_trigger_send : out std_logic + ); + +end entity; + +architecture rtl of Altera_UP_SD_Card_Clock is + + -- Local wires + -- REGISTERED + signal counter : std_logic_vector(6 downto 0); + signal local_mode : std_logic; + -- UNREGISTERED +begin + process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + counter <= (OTHERS => '0'); + local_mode <= '0'; + else + if (rising_edge(i_clock)) then + if (i_enable = '1') then + counter <= counter + '1'; + end if; + -- Change the clock pulse only when at the positive edge of the clock + if (counter = "1000000") then + local_mode <= i_mode; + end if; + end if; + end if; + end process; + + o_clock_mode <= local_mode; + o_SD_clock <= counter(6) when (local_mode = '0') else counter(1); + o_trigger_receive <= '1' when ((local_mode = '0') and (counter = "0111111")) else + ((not counter(1)) and (counter(0))) when (local_mode = '1') else '0'; + o_trigger_send <= '1' when ((local_mode = '0') and (counter = "0011111")) else + ((counter(1)) and (counter(0))) when (local_mode = '1') else '0'; + +end rtl; \ No newline at end of file diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd new file mode 100644 index 0000000..c020fbd --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Control_FSM.vhd @@ -0,0 +1,347 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +---------------------------------------------------------------------------------------------------------------- +-- This is an FSM that controls the SD Card interface circuitry. +-- +-- On reset, the FSM will initiate a predefined set of commands in an attempt to connect to the SD Card. +-- When successful, it will allow commands to be issued to the SD Card, otherwise it will return a signal that +-- no card is present in the SD Card slot. +-- +-- NOTES/REVISIONS: +---------------------------------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Altera_UP_SD_Card_Control_FSM is + generic ( + PREDEFINED_COMMAND_GET_STATUS : STD_LOGIC_VECTOR(3 downto 0) := "1001" + ); + port + ( + -- Clock and Reset signals + i_clock : in STD_LOGIC; + i_reset_n : in STD_LOGIC; + + -- FSM Inputs + i_user_command_ready : in std_logic; + i_response_received : in STD_LOGIC; + i_response_timed_out : in STD_LOGIC; + i_response_crc_passed : in STD_LOGIC; + i_command_sent : in STD_LOGIC; + i_powerup_busy_n : in STD_LOGIC; + i_clocking_pulse_enable : in std_logic; + i_current_clock_mode : in std_logic; + i_user_message_valid : in std_logic; + i_last_cmd_was_55 : in std_logic; + i_allow_partial_rw : in std_logic; + + -- FSM Outputs + o_generate_command : out STD_LOGIC; + o_predefined_command_ID : out STD_LOGIC_VECTOR(3 downto 0); + o_receive_response : out STD_LOGIC; + o_drive_CMD_line : out STD_LOGIC; + o_SD_clock_mode : out STD_LOGIC; -- 0 means slow clock for card identification, 1 means fast clock for transfer mode. + o_resetting : out std_logic; + o_card_connected : out STD_LOGIC; + o_command_completed : out std_logic; + o_clear_response_register : out std_logic; + o_enable_clock_generator : out std_logic + ); + +end entity; + +architecture rtl of Altera_UP_SD_Card_Control_FSM is + + -- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state + -- of the switches. + type state_type is (s_RESET, s_WAIT_74_CYCLES, s_GENERATE_PREDEFINED_COMMAND, s_WAIT_PREDEFINED_COMMAND_TRANSMITTED, s_WAIT_PREDEFINED_COMMAND_RESPONSE, + s_GO_TO_NEXT_COMMAND, s_TOGGLE_CLOCK_FREQUENCY, s_AWAIT_USER_COMMAND, s_REACTIVATE_CLOCK, + s_GENERATE_COMMAND, s_SEND_COMMAND, s_WAIT_RESPONSE, s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE, s_WAIT_DEASSERT, + s_PERIODIC_STATUS_CHECK); + + -- Register to hold the current state + signal current_state : state_type; + signal next_state : state_type; + + ------------------- + -- Local signals + ------------------- + -- REGISTERED + signal SD_clock_mode, waiting_for_vdd_setup : std_logic; + signal id_sequence_step_index : std_logic_vector(3 downto 0); + signal delay_counter : std_logic_vector(6 downto 0); + signal periodic_status_check : std_logic_vector(23 downto 0); + -- UNREGISTERED + +begin + -- Define state transitions. + state_transitions: process (current_state, i_command_sent, i_response_received, id_sequence_step_index, + i_response_timed_out, i_response_crc_passed, delay_counter, waiting_for_vdd_setup, + i_user_command_ready, i_clocking_pulse_enable, i_current_clock_mode, + i_user_message_valid, i_last_cmd_was_55, periodic_status_check) + begin + case current_state is + when s_RESET => + -- Reset local registers and begin identification process. + next_state <= s_WAIT_74_CYCLES; + + when s_WAIT_74_CYCLES => + -- Wait 74 cycles before the card can be sent commands to. + if (delay_counter = "1001010") then + next_state <= s_GENERATE_PREDEFINED_COMMAND; + else + next_state <= s_WAIT_74_CYCLES; + end if; + + when s_GENERATE_PREDEFINED_COMMAND => + -- Generate a predefined command to the SD card. This is the identification process for the SD card. + next_state <= s_WAIT_PREDEFINED_COMMAND_TRANSMITTED; + + when s_WAIT_PREDEFINED_COMMAND_TRANSMITTED => + -- Send a predefined command to the SD card. This is the identification process for the SD card. + if (i_command_sent = '1') then + next_state <= s_WAIT_PREDEFINED_COMMAND_RESPONSE; + else + next_state <= s_WAIT_PREDEFINED_COMMAND_TRANSMITTED; + end if; + + when s_WAIT_PREDEFINED_COMMAND_RESPONSE => + -- Wait for a response from SD card. + if (i_response_received = '1') then + if (i_response_timed_out = '1') then + if (waiting_for_vdd_setup = '1') then + next_state <= s_GO_TO_NEXT_COMMAND; + else + next_state <= s_RESET; + end if; + else + if (i_response_crc_passed = '0') then + next_state <= s_GENERATE_PREDEFINED_COMMAND; + else + next_state <= s_GO_TO_NEXT_COMMAND; + end if; + end if; + else + next_state <= s_WAIT_PREDEFINED_COMMAND_RESPONSE; + end if; + + when s_GO_TO_NEXT_COMMAND => + -- Process the next command in the ID sequence. + if (id_sequence_step_index = PREDEFINED_COMMAND_GET_STATUS) then + next_state <= s_TOGGLE_CLOCK_FREQUENCY; + else + next_state <= s_GENERATE_PREDEFINED_COMMAND; + end if; + + when s_TOGGLE_CLOCK_FREQUENCY => + -- Now that the card has been initialized, increase the SD card clock frequency to 25MHz. + -- Wait for the clock generator to switch operating mode before proceeding further. + if (i_current_clock_mode = '1') then + next_state <= s_AWAIT_USER_COMMAND; + else + next_state <= s_TOGGLE_CLOCK_FREQUENCY; + end if; + + when s_AWAIT_USER_COMMAND => + -- Wait for the user to send a command to the SD card + if (i_user_command_ready = '1') then + next_state <= s_REACTIVATE_CLOCK; + else + -- Every 5 million cycles, or 0.1 of a second. + if (periodic_status_check = "010011000100101101000000") then + next_state <= s_PERIODIC_STATUS_CHECK; + else + next_state <= s_AWAIT_USER_COMMAND; + end if; + end if; + + when s_PERIODIC_STATUS_CHECK => + -- Update status every now and then. + next_state <= s_GENERATE_PREDEFINED_COMMAND; + + when s_REACTIVATE_CLOCK => + -- Activate the clock signal and wait 8 clock cycles. + if (delay_counter = "0001000") then + next_state <= s_GENERATE_COMMAND; + else + next_state <= s_REACTIVATE_CLOCK; + end if; + + when s_GENERATE_COMMAND => + -- Generate user command. If valid, proceed further. Otherwise, indicate that the command is invalid. + if (i_user_message_valid = '0') then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_SEND_COMMAND; + end if; + + when s_SEND_COMMAND => + -- Wait for the command to be sent. + if (i_command_sent = '1') then + next_state <= s_WAIT_RESPONSE; + else + next_state <= s_SEND_COMMAND; + end if; + + when s_WAIT_RESPONSE => + -- Wait for the SD card to respond. + if (i_response_received = '1') then + if (i_response_timed_out = '1') then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE; + end if; + else + next_state <= s_WAIT_RESPONSE; + end if; + + when s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE => + -- Wait for a positive clock edge before you disable the clock. + if (i_clocking_pulse_enable = '1') then + next_state <= s_WAIT_DEASSERT; + else + next_state <= s_WAIT_FOR_CLOCK_EDGE_BEFORE_DISABLE; + end if; + + when s_WAIT_DEASSERT => + -- wait for the user to release command generation request. + if (i_user_command_ready = '1') then + next_state <= s_WAIT_DEASSERT; + else + if (i_last_cmd_was_55 = '1') then + next_state <= s_AWAIT_USER_COMMAND; + else + -- Send a get status command to obtain the result of sending the last command. + next_state <= s_GENERATE_PREDEFINED_COMMAND; + end if; + end if; + + when others => + -- Make sure to start in the reset state if the circuit powers up in an odd state. + next_state <= s_RESET; + end case; + end process; + + -- State registers. + state_registers: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + current_state <= s_RESET; + elsif (rising_edge(i_clock)) then + current_state <= next_state; + end if; + end process; + + -- Local FFs: + local_ffs:process ( i_clock, i_reset_n, i_powerup_busy_n, current_state, + id_sequence_step_index, i_response_received, i_response_timed_out, + i_allow_partial_rw) + begin + if (i_reset_n = '0') then + SD_clock_mode <= '0'; + id_sequence_step_index <= (OTHERS => '0'); + periodic_status_check <= (OTHERS => '0'); + waiting_for_vdd_setup <= '0'; + elsif (rising_edge(i_clock)) then + -- Set SD clock mode to 0 initially, thereby using a clock with frequency between 100 kHz and 400 kHz as + -- per SD card specifications. When the card is initialized change the clock to run at 25 MHz. + if (current_state = s_WAIT_DEASSERT) then + periodic_status_check <= (OTHERS => '0'); + elsif (current_state = s_AWAIT_USER_COMMAND) then + periodic_status_check <= periodic_status_check + '1'; + end if; + + if (current_state = s_RESET) then + SD_clock_mode <= '0'; + elsif (current_state = s_TOGGLE_CLOCK_FREQUENCY) then + SD_clock_mode <= '1'; + end if; + -- Update the ID sequence step as needed. + if (current_state = s_RESET) then + id_sequence_step_index <= (OTHERS => '0'); + elsif (current_state = s_GO_TO_NEXT_COMMAND) then + if ((i_powerup_busy_n = '0') and (id_sequence_step_index = "0010")) then + id_sequence_step_index <= "0001"; + else + if (id_sequence_step_index = "0110") then + if (i_allow_partial_rw = '0') then + -- If partial read-write not allowed, then skip SET_BLK_LEN command - it will fail. + id_sequence_step_index <= "1000"; + else + id_sequence_step_index <= "0111"; + end if; + else + id_sequence_step_index <= id_sequence_step_index + '1'; + end if; + end if; + elsif (current_state = s_WAIT_DEASSERT) then + if (i_last_cmd_was_55 = '0') then + -- After each command execute a get status command. + id_sequence_step_index <= PREDEFINED_COMMAND_GET_STATUS; + end if; + elsif (current_state = s_PERIODIC_STATUS_CHECK) then + id_sequence_step_index <= PREDEFINED_COMMAND_GET_STATUS; + end if; + + -- Do not reset the card when SD card is having its VDD set up. Wait for it to respond, this may take some time. + if (id_sequence_step_index = "0010") then + waiting_for_vdd_setup <= '1'; + elsif ((id_sequence_step_index = "0011") or (current_state = s_RESET)) then + waiting_for_vdd_setup <= '0'; + end if; + + end if; + end process; + + -- Counter that counts to 74 to delay any commands. + initial_delay_counter: process(i_clock, i_reset_n, i_clocking_pulse_enable ) + begin + if (i_reset_n = '0') then + delay_counter <= (OTHERS => '0'); + elsif (rising_edge(i_clock)) then + if ((current_state = s_RESET) or (current_state = s_AWAIT_USER_COMMAND))then + delay_counter <= (OTHERS => '0'); + elsif (((current_state = s_WAIT_74_CYCLES) or (current_state = s_REACTIVATE_CLOCK)) and + (i_clocking_pulse_enable = '1')) then + delay_counter <= delay_counter + '1'; + end if; + end if; + end process; + + -- FSM outputs. + o_SD_clock_mode <= SD_clock_mode; + o_generate_command <= '1' when ((current_state = s_GENERATE_PREDEFINED_COMMAND) or + (current_state = s_GENERATE_COMMAND)) + else '0'; + o_receive_response <= '1' when ((current_state = s_WAIT_PREDEFINED_COMMAND_RESPONSE) or + (current_state = s_WAIT_RESPONSE)) + else '0'; + o_drive_CMD_line <= '1' when ( (current_state = s_WAIT_PREDEFINED_COMMAND_TRANSMITTED) or + (current_state = s_SEND_COMMAND)) else '0'; + o_predefined_command_ID <= id_sequence_step_index; + o_card_connected <= '1' when (id_sequence_step_index(3) = '1') and ( + (id_sequence_step_index(2) = '1') or + (id_sequence_step_index(1) = '1') or + (id_sequence_step_index(0) = '1')) + else '0'; + o_resetting <= '1' when (current_state = s_RESET) else '0'; + o_command_completed <= '1' when (current_state = s_WAIT_DEASSERT) else '0'; + o_enable_clock_generator <= '0' when (current_state = s_AWAIT_USER_COMMAND) else '1'; + o_clear_response_register <= '1' when (current_state = s_REACTIVATE_CLOCK) else '0'; + +end rtl; + diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd new file mode 100644 index 0000000..ba2f743 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Interface.vhd @@ -0,0 +1,518 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +------------------------------------------------------------------------------------- +-- This module is an interface to the Secure Data Card. This module is intended to be +-- used with the DE2 board. +-- +-- This version of the interface supports only a 1-bit serial data transfer. This +-- allows the interface to support a MultiMedia card as well. +-- +-- NOTES/REVISIONS: +------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity Altera_UP_SD_Card_Interface is + + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + + -- Command interface + b_SD_cmd : inout std_logic; + b_SD_dat : inout std_logic; + b_SD_dat3 : inout std_logic; + i_command_ID : in std_logic_vector(5 downto 0); + i_argument : in std_logic_vector(31 downto 0); + i_user_command_ready : in std_logic; + + o_SD_clock : out std_logic; + o_card_connected : out std_logic; + o_command_completed : out std_logic; + o_command_valid : out std_logic; + o_command_timed_out : out std_logic; + o_command_crc_failed : out std_logic; + + -- Buffer access + i_buffer_enable : in std_logic; + i_buffer_address : in std_logic_vector(7 downto 0); + i_buffer_write : in std_logic; + i_buffer_data_in : in std_logic_vector(15 downto 0); + o_buffer_data_out : out std_logic_vector(15 downto 0); + + -- Show SD Card registers as outputs + o_SD_REG_card_identification_number : out std_logic_vector(127 downto 0); + o_SD_REG_relative_card_address : out std_logic_vector(15 downto 0); + o_SD_REG_operating_conditions_register : out std_logic_vector(31 downto 0); + o_SD_REG_card_specific_data : out std_logic_vector(127 downto 0); + o_SD_REG_status_register : out std_logic_vector(31 downto 0); + o_SD_REG_response_R1 : out std_logic_vector(31 downto 0); + o_SD_REG_status_register_valid : out std_logic + ); + +end entity; + +architecture rtl of Altera_UP_SD_Card_Interface is + + component Altera_UP_SD_Card_Clock + + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_enable : in std_logic; + i_mode : in std_logic; -- 0 for card identification mode, 1 for data transfer mode. + o_SD_clock : out std_logic; + o_clock_mode : out std_logic; + o_trigger_receive : out std_logic; + o_trigger_send : out std_logic + ); + + end component; + + component Altera_UP_SD_CRC7_Generator + port + ( + i_clock : in std_logic; + i_enable : in std_logic; + i_reset_n : in std_logic; + i_shift : in std_logic; + i_datain : in std_logic; + o_dataout : out std_logic; + o_crcout : out std_logic_vector(6 downto 0) + ); + end component; + + component Altera_UP_SD_CRC16_Generator + port + ( + i_clock : in std_logic; + i_enable : in std_logic; + i_reset_n : in std_logic; + i_shift : in std_logic; + i_datain : in std_logic; + o_dataout : out std_logic; + o_crcout : out std_logic_vector(15 downto 0) + ); + end component; + + component Altera_UP_SD_Signal_Trigger + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_signal : in std_logic; + o_trigger : out std_logic + ); + end component; + + component Altera_UP_SD_Card_48_bit_Command_Generator + generic ( + -- Basic commands + COMMAND_0_GO_IDLE : STD_LOGIC_VECTOR(5 downto 0) := "000000"; + COMMAND_2_ALL_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "000010"; + COMMAND_3_SEND_RCA : STD_LOGIC_VECTOR(5 downto 0) := "000011"; + COMMAND_4_SET_DSR : STD_LOGIC_VECTOR(5 downto 0) := "000100"; + COMMAND_6_SWITCH_FUNCTION : STD_LOGIC_VECTOR(5 downto 0) := "000110"; + COMMAND_7_SELECT_CARD : STD_LOGIC_VECTOR(5 downto 0) := "000111"; + COMMAND_9_SEND_CSD : STD_LOGIC_VECTOR(5 downto 0) := "001001"; + COMMAND_10_SEND_CID : STD_LOGIC_VECTOR(5 downto 0) := "001010"; + COMMAND_12_STOP_TRANSMISSION : STD_LOGIC_VECTOR(5 downto 0) := "001100"; + COMMAND_13_SEND_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101"; + COMMAND_15_GO_INACTIVE : STD_LOGIC_VECTOR(5 downto 0) := "001111"; + -- Block oriented read/write/lock commands + COMMAND_16_SET_BLOCK_LENGTH : STD_LOGIC_VECTOR(5 downto 0) := "010000"; + -- Block oriented read commands + COMMAND_17_READ_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "010001"; + COMMAND_18_READ_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010010"; + -- Block oriented write commands + COMMAND_24_WRITE_BLOCK : STD_LOGIC_VECTOR(5 downto 0) := "011000"; + COMMAND_25_WRITE_MULTIPLE_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "011001"; + COMMAND_27_PROGRAM_CSD : STD_LOGIC_VECTOR(5 downto 0) := "011011"; + -- Block oriented write-protection commands + COMMAND_28_SET_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011100"; + COMMAND_29_CLEAR_WRITE_PROTECT : STD_LOGIC_VECTOR(5 downto 0) := "011101"; + COMMAND_30_SEND_PROTECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "011110"; + -- Erase commands + COMMAND_32_ERASE_BLOCK_START : STD_LOGIC_VECTOR(5 downto 0) := "100000"; + COMMAND_33_ERASE_BLOCK_END : STD_LOGIC_VECTOR(5 downto 0) := "100001"; + COMMAND_38_ERASE_SELECTED_GROUPS : STD_LOGIC_VECTOR(5 downto 0) := "100110"; + -- Block lock commands + COMMAND_42_LOCK_UNLOCK : STD_LOGIC_VECTOR(5 downto 0) := "101010"; + -- Command Type Settings + COMMAND_55_APP_CMD : STD_LOGIC_VECTOR(5 downto 0) := "110111"; + COMMAND_56_GEN_CMD : STD_LOGIC_VECTOR(5 downto 0) := "111000"; + -- Application Specific commands - must be preceeded with command 55. + ACOMMAND_6_SET_BUS_WIDTH : STD_LOGIC_VECTOR(5 downto 0) := "000110"; + ACOMMAND_13_SD_STATUS : STD_LOGIC_VECTOR(5 downto 0) := "001101"; + ACOMMAND_22_SEND_NUM_WR_BLOCKS : STD_LOGIC_VECTOR(5 downto 0) := "010100"; + ACOMMAND_23_SET_BLK_ERASE_COUNT : STD_LOGIC_VECTOR(5 downto 0) := "010101"; + ACOMMAND_41_SEND_OP_CONDITION : STD_LOGIC_VECTOR(5 downto 0) := "101001"; + ACOMMAND_42_SET_CLR_CARD_DETECT : STD_LOGIC_VECTOR(5 downto 0) := "101010"; + ACOMMAND_51_SEND_SCR : STD_LOGIC_VECTOR(5 downto 0) := "110011"; + -- First custom_command + FIRST_NON_PREDEFINED_COMMAND : STD_LOGIC_VECTOR(3 downto 0) := "1010" + ); + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_message_bit_out : in std_logic; + i_command_ID : in std_logic_vector(5 downto 0); + i_argument : in std_logic_vector(31 downto 0); + i_predefined_message : in std_logic_vector(3 downto 0); + i_generate : in std_logic; + i_DSR : in std_logic_vector(15 downto 0); + i_OCR : in std_logic_vector(31 downto 0); + i_RCA : in std_logic_vector(15 downto 0); + o_dataout : out std_logic; + o_message_done : out std_logic; + o_valid : out std_logic; + o_returning_ocr : out std_logic; + o_returning_cid : out std_logic; + o_returning_rca : out std_logic; + o_returning_csd : out std_logic; + o_returning_status : out std_logic; + o_data_read : out std_logic; + o_data_write : out std_logic; + o_wait_cmd_busy : out std_logic; + o_last_cmd_was_55 : out std_logic; + o_response_type : out std_logic_vector(2 downto 0) + ); + end component; + + component Altera_UP_SD_Card_Response_Receiver + generic ( + TIMEOUT : std_logic_vector(7 downto 0) := "00111000"; + BUSY_WAIT : std_logic_vector(7 downto 0) := "00110000"; + PROCESSING_DELAY : std_logic_vector(7 downto 0) := "00001000" + ); + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_begin : in std_logic; + i_scan_pulse : in std_logic; + i_datain : in std_logic; + i_wait_cmd_busy : in std_logic; + i_response_type : in std_logic_vector(2 downto 0); + o_data : out std_logic_vector(127 downto 0); + o_CRC_passed : out std_logic; + o_timeout : out std_logic; + o_done : out std_logic + ); + end component; + + component Altera_UP_SD_Card_Control_FSM + generic ( + PREDEFINED_COMMAND_GET_STATUS : STD_LOGIC_VECTOR(3 downto 0) := "1001" + ); + port + ( + -- Clock and Reset signals + i_clock : in STD_LOGIC; + i_reset_n : in STD_LOGIC; + + -- FSM Inputs + i_user_command_ready : in std_logic; + i_response_received : in STD_LOGIC; + i_response_timed_out : in STD_LOGIC; + i_response_crc_passed : in STD_LOGIC; + i_command_sent : in STD_LOGIC; + i_powerup_busy_n : in STD_LOGIC; + i_clocking_pulse_enable : in std_logic; + i_current_clock_mode : in std_logic; + i_user_message_valid : in std_logic; + i_last_cmd_was_55 : in std_logic; + i_allow_partial_rw : in std_logic; + + -- FSM Outputs + o_generate_command : out STD_LOGIC; + o_predefined_command_ID : out STD_LOGIC_VECTOR(3 downto 0); + o_receive_response : out STD_LOGIC; + o_drive_CMD_line : out STD_LOGIC; + o_SD_clock_mode : out STD_LOGIC; -- 0 means slow clock for card identification, 1 means fast clock for transfer mode. + o_resetting : out std_logic; + o_card_connected : out STD_LOGIC; + o_command_completed : out std_logic; + o_clear_response_register : out std_logic; + o_enable_clock_generator : out std_logic + ); + end component; + + component Altera_UP_SD_Card_Buffer + generic ( + TIMEOUT : std_logic_vector(15 downto 0) := "1111111111111111"; + BUSY_WAIT : std_logic_vector(15 downto 0) := "0000001111110000" + ); + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + + -- 1 bit port to transmit and receive data on the data line. + i_begin : in std_logic; + i_sd_clock_pulse_trigger : in std_logic; + i_transmit : in std_logic; + i_1bit_data_in : in std_logic; + o_1bit_data_out : out std_logic; + o_operation_complete : out std_logic; + o_crc_passed : out std_logic; + o_timed_out : out std_logic; + o_dat_direction : out std_logic; -- set to 1 to send data, set to 0 to receive it. + + -- 16 bit port to be accessed by a user circuit. + i_enable_16bit_port : in std_logic; + i_address_16bit_port : in std_logic_vector(7 downto 0); + i_write_16bit : in std_logic; + i_16bit_data_in : in std_logic_vector(15 downto 0); + o_16bit_data_out : out std_logic_vector(15 downto 0) + ); + end component; + + -- Local wires + -- REGISTERED + signal sd_mode : std_logic; + -- SD Card Registers: + signal SD_REG_card_identification_number : std_logic_vector(127 downto 0); + signal SD_REG_response_R1 : std_logic_vector(31 downto 0); + signal SD_REG_relative_card_address : std_logic_vector(15 downto 0); + signal SD_REG_driver_stage_register : std_logic_vector(15 downto 0); + signal SD_REG_card_specific_data : std_logic_vector(127 downto 0); + signal SD_REG_operating_conditions_register : std_logic_vector(31 downto 0); + signal SD_REG_status_register : std_logic_vector(31 downto 0); + signal SD_REG_status_register_valid : std_logic; + -- UNREGISTERED + signal data_from_buffer : std_logic_vector(15 downto 0); + signal clock_generator_mode, enable_generator, SD_clock, create_message : std_logic; + signal send_next_bit, receive_next_bit : std_logic; + signal timed_out, response_done, passed_crc, begin_reading_response, resetting : std_logic; + signal returning_cid, returning_rca, returning_csd, returning_ocr : std_logic; + signal response_type : std_logic_vector(2 downto 0); + signal message_valid, messange_sent, data_to_CMD_line, CMD_tristate_buffer_enable, message_sent : std_logic; + signal predef_message_ID : std_logic_vector(3 downto 0); + signal receive_data_out : std_logic_vector(127 downto 0); + signal data_line_done, data_line_crc, data_line_timeout, data_line_direction, data_line_out : std_logic; + signal data_read, data_write, wait_cmd_busy, clear_response_register : std_logic; + signal response_done_combined : std_logic; + signal timeout_combined : std_logic; + signal crc_combined, allow_partial_rw : std_logic; + signal begin_data_line_operations, last_cmd_was_55, message_sent_trigger, returning_status : std_logic; + signal data_line_sd_clock_pulse_trigger : std_logic; +begin + -- Glue logic + SD_REG_driver_stage_register <= (OTHERS => '0'); + response_done_combined <= (response_done and (not data_read) and (not data_write)) or + (response_done and (data_read or data_write) and data_line_done); + timeout_combined <= (timed_out and (not data_read) and (not data_write)) or + (timed_out and (data_read or data_write) and data_line_timeout); + crc_combined <= (passed_crc and (not data_read) and (not data_write)) or + (passed_crc and (data_read or data_write) and data_line_crc); + begin_data_line_operations <= (data_read and message_sent) or (data_write and response_done); + + -- Partial read and write are only allowed when both bit 79 (partial read allowed) is high and + -- bit 21 (partial write allowed) is high. + allow_partial_rw <= SD_REG_card_specific_data(79) and SD_REG_card_specific_data(21); + + -- SD Card control registers + control_regs: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + SD_REG_operating_conditions_register <= (OTHERS => '0'); + SD_REG_card_identification_number <= (OTHERS => '0'); + SD_REG_relative_card_address <= (OTHERS => '0'); + SD_REG_card_specific_data <= (OTHERS => '0'); + SD_REG_status_register <= (OTHERS => '0'); + SD_REG_response_R1 <= (OTHERS => '1'); + SD_REG_status_register_valid <= '0'; + elsif (rising_edge(i_clock)) then + if ((response_type = "001") and (response_done = '1') and (returning_status = '0') and (clear_response_register = '0')) then + SD_REG_response_R1 <= receive_data_out(31 downto 0); + elsif (clear_response_register = '1') then + SD_REG_response_R1 <= (OTHERS => '1'); + end if; + if (resetting = '1') then + SD_REG_operating_conditions_register <= (OTHERS => '0'); + elsif ((returning_ocr = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then + SD_REG_operating_conditions_register <= receive_data_out(31 downto 0); + end if; + if ((returning_cid = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then + SD_REG_card_identification_number <= receive_data_out; + end if; + if ((returning_rca = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then + SD_REG_relative_card_address <= receive_data_out(31 downto 16); + end if; + if ((returning_csd = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then + SD_REG_card_specific_data <= receive_data_out; + end if; + if (message_sent_trigger = '1') then + SD_REG_status_register_valid <= '0'; + elsif ((returning_status = '1') and (passed_crc = '1') and (response_done = '1') and (timed_out = '0')) then + SD_REG_status_register <= receive_data_out(31 downto 0); + SD_REG_status_register_valid <= '1'; + end if; + end if; + end process; + + -- Instantiated components + command_generator: Altera_UP_SD_Card_48_bit_Command_Generator PORT MAP + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_message_bit_out => send_next_bit, + i_command_ID => i_command_ID, + i_argument => i_argument, + i_predefined_message => predef_message_ID, + i_generate => create_message, + i_DSR => SD_REG_driver_stage_register, + i_OCR => SD_REG_operating_conditions_register, + i_RCA => SD_REG_relative_card_address, + o_dataout => data_to_CMD_line, + o_message_done => message_sent, + o_valid => message_valid, + o_returning_ocr => returning_ocr, + o_returning_cid => returning_cid, + o_returning_rca => returning_rca, + o_returning_csd => returning_csd, + o_returning_status => returning_status, + o_data_read => data_read, + o_data_write => data_write, + o_wait_cmd_busy => wait_cmd_busy, + o_last_cmd_was_55 => last_cmd_was_55, + o_response_type => response_type + ); + + response_receiver: Altera_UP_SD_Card_Response_Receiver PORT MAP + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_begin => begin_reading_response, + i_scan_pulse => receive_next_bit, + i_datain => b_SD_cmd, + i_response_type => response_type, + i_wait_cmd_busy => wait_cmd_busy, + o_data => receive_data_out, + o_CRC_passed => passed_crc, + o_timeout => timed_out, + o_done => response_done + ); + + control_FSM: Altera_UP_SD_Card_Control_FSM PORT MAP + ( + -- Clock and Reset signals + i_clock => i_clock, + i_reset_n => i_reset_n, + + -- FSM Inputs + i_user_command_ready => i_user_command_ready, + i_clocking_pulse_enable => receive_next_bit, + i_response_received => response_done_combined, + i_response_timed_out => timeout_combined, + i_response_crc_passed => crc_combined, + i_command_sent => message_sent, + i_powerup_busy_n => SD_REG_operating_conditions_register(31), + i_current_clock_mode => clock_generator_mode, + i_user_message_valid => message_valid, + i_last_cmd_was_55 => last_cmd_was_55, + i_allow_partial_rw => allow_partial_rw, + + -- FSM Outputs + o_generate_command => create_message, + o_predefined_command_ID => predef_message_ID, + o_receive_response => begin_reading_response, + o_drive_CMD_line => CMD_tristate_buffer_enable, + o_SD_clock_mode => sd_mode, -- 0 means slow clock for card identification, 1 means fast clock for transfer mode. + o_card_connected => o_card_connected, + o_command_completed => o_command_completed, + o_resetting => resetting, + o_clear_response_register => clear_response_register, + o_enable_clock_generator => enable_generator + ); + + clock_generator: Altera_UP_SD_Card_Clock PORT MAP + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_mode => sd_mode, + i_enable => enable_generator, + o_SD_clock => SD_clock, + o_clock_mode => clock_generator_mode, + o_trigger_receive => receive_next_bit, + o_trigger_send => send_next_bit + ); + + SD_clock_pulse_trigger: Altera_UP_SD_Signal_Trigger PORT MAP + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_signal => message_sent, + o_trigger => message_sent_trigger + ); + + data_line: Altera_UP_SD_Card_Buffer + port map + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + + -- 1 bit port to transmit and receive data on the data line. + i_begin => begin_data_line_operations, + i_sd_clock_pulse_trigger => data_line_sd_clock_pulse_trigger, + i_transmit => data_write, + i_1bit_data_in => b_SD_dat, + o_1bit_data_out => data_line_out, + o_operation_complete => data_line_done, + o_crc_passed => data_line_crc, + o_timed_out => data_line_timeout, + o_dat_direction => data_line_direction, + + -- 16 bit port to be accessed by a user circuit. + i_enable_16bit_port => i_buffer_enable, + i_address_16bit_port => i_buffer_address, + i_write_16bit => i_buffer_write, + i_16bit_data_in => i_buffer_data_in, + o_16bit_data_out => data_from_buffer + ); + data_line_sd_clock_pulse_trigger <= (data_write and send_next_bit) or ((not data_write) and receive_next_bit); + + -- Buffer output registers. + buff_regs: process(i_clock, i_reset_n, data_from_buffer) + begin + if (i_reset_n = '0') then + o_buffer_data_out <= (OTHERS=> '0'); + elsif (rising_edge(i_clock)) then + o_buffer_data_out <= data_from_buffer; + end if; + end process; + + -- Circuit outputs. + o_command_valid <= message_valid; + o_command_timed_out <= timeout_combined; + o_command_crc_failed <= not crc_combined; + o_SD_clock <= SD_clock; + b_SD_cmd <= data_to_CMD_line when (CMD_tristate_buffer_enable = '1') else 'Z'; + b_SD_dat <= data_line_out when (data_line_direction = '1') else 'Z'; + b_SD_dat3 <= 'Z'; -- Set SD card to SD mode. + -- SD card registers + o_SD_REG_card_identification_number <= SD_REG_card_identification_number; + o_SD_REG_relative_card_address <= SD_REG_relative_card_address; + o_SD_REG_operating_conditions_register <= SD_REG_operating_conditions_register; + o_SD_REG_card_specific_data <= SD_REG_card_specific_data; + o_SD_REG_status_register <= SD_REG_status_register; + o_SD_REG_response_R1 <= SD_REG_response_R1; + o_SD_REG_status_register_valid <= SD_REG_status_register_valid; + +end rtl; diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd new file mode 100644 index 0000000..5b1d0cc --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Memory_Block.vhd @@ -0,0 +1,296 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +-- megafunction wizard: %RAM: 2-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: Altera_UP_SD_Card_Memory_Block.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 8.0 Build 215 05/29/2008 SJ Full Version +-- ************************************************************ + + +--Copyright (C) 1991-2013 Altera Corporation +--Your use of Altera Corporation's design tools, logic functions +--and other software and tools, and its AMPP partner logic +--functions, and any output files from any of the foregoing +--(including device programming or simulation files), and any +--associated documentation or information are expressly subject +--to the terms and conditions of the Altera Program License +--Subscription Agreement, Altera MegaCore Function License +--Agreement, or other applicable license agreement, including, +--without limitation, that your use is for the sole purpose of +--programming logic devices manufactured by Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY Altera_UP_SD_Card_Memory_Block IS + PORT + ( + address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + clock_a : IN STD_LOGIC ; + clock_b : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + enable_a : IN STD_LOGIC := '1'; + enable_b : IN STD_LOGIC := '1'; + wren_a : IN STD_LOGIC := '1'; + wren_b : IN STD_LOGIC := '1'; + q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0) + ); +END Altera_UP_SD_Card_Memory_Block; + + +ARCHITECTURE SYN OF altera_up_sd_card_memory_block IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (15 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_reg_b : STRING; + clock_enable_input_a : STRING; + clock_enable_input_b : STRING; + clock_enable_output_a : STRING; + clock_enable_output_b : STRING; + indata_reg_b : STRING; + init_file : STRING; + init_file_layout : STRING; + intended_device_family : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + numwords_b : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_aclr_b : STRING; + outdata_reg_a : STRING; + outdata_reg_b : STRING; + power_up_uninitialized : STRING; + widthad_a : NATURAL; + widthad_b : NATURAL; + width_a : NATURAL; + width_b : NATURAL; + width_byteena_a : NATURAL; + width_byteena_b : NATURAL; + wrcontrol_wraddress_reg_b : STRING + ); + PORT ( + clocken0 : IN STD_LOGIC ; + clocken1 : IN STD_LOGIC ; + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + wren_b : IN STD_LOGIC ; + clock1 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (7 DOWNTO 0); + address_b : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); + q_b : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); + data_b : IN STD_LOGIC_VECTOR (0 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q_a <= sub_wire0(15 DOWNTO 0); + q_b <= sub_wire1(0 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_reg_b => "CLOCK1", + clock_enable_input_a => "NORMAL", + clock_enable_input_b => "NORMAL", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => "initial_data.mif", + init_file_layout => "PORT_A", + intended_device_family => "Cyclone II", + lpm_type => "altsyncram", + numwords_a => 256, + numwords_b => 4096, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => "UNREGISTERED", + outdata_reg_b => "UNREGISTERED", + power_up_uninitialized => "FALSE", + widthad_a => 8, + widthad_b => 12, + width_a => 16, + width_b => 1, + width_byteena_a => 1, + width_byteena_b => 1, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + clocken0 => enable_a, + clocken1 => enable_b, + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +-- Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +-- Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +-- Retrieval info: PRIVATE: CLRdata NUMERIC "0" +-- Retrieval info: PRIVATE: CLRq NUMERIC "0" +-- Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +-- Retrieval info: PRIVATE: CLRrren NUMERIC "0" +-- Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +-- Retrieval info: PRIVATE: CLRwren NUMERIC "0" +-- Retrieval info: PRIVATE: Clock NUMERIC "5" +-- Retrieval info: PRIVATE: Clock_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clock_B NUMERIC "0" +-- Retrieval info: PRIVATE: ECC NUMERIC "0" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MEMSIZE NUMERIC "4096" +-- Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "1" +-- Retrieval info: PRIVATE: MIFfilename STRING "initial_data.mif" +-- Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" +-- Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +-- Retrieval info: PRIVATE: REGdata NUMERIC "1" +-- Retrieval info: PRIVATE: REGq NUMERIC "0" +-- Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" +-- Retrieval info: PRIVATE: REGrren NUMERIC "0" +-- Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +-- Retrieval info: PRIVATE: REGwren NUMERIC "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" +-- Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +-- Retrieval info: PRIVATE: VarWidth NUMERIC "1" +-- Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "16" +-- Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "1" +-- Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "16" +-- Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "1" +-- Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" +-- Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +-- Retrieval info: PRIVATE: enable NUMERIC "1" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "NORMAL" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" +-- Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK1" +-- Retrieval info: CONSTANT: INIT_FILE STRING "initial_data.mif" +-- Retrieval info: CONSTANT: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256" +-- Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "4096" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8" +-- Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "12" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "16" +-- Retrieval info: CONSTANT: WIDTH_B NUMERIC "1" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" +-- Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK1" +-- Retrieval info: USED_PORT: address_a 0 0 8 0 INPUT NODEFVAL address_a[7..0] +-- Retrieval info: USED_PORT: address_b 0 0 12 0 INPUT NODEFVAL address_b[11..0] +-- Retrieval info: USED_PORT: clock_a 0 0 0 0 INPUT NODEFVAL clock_a +-- Retrieval info: USED_PORT: clock_b 0 0 0 0 INPUT NODEFVAL clock_b +-- Retrieval info: USED_PORT: data_a 0 0 16 0 INPUT NODEFVAL data_a[15..0] +-- Retrieval info: USED_PORT: data_b 0 0 1 0 INPUT NODEFVAL data_b[0..0] +-- Retrieval info: USED_PORT: enable_a 0 0 0 0 INPUT VCC enable_a +-- Retrieval info: USED_PORT: enable_b 0 0 0 0 INPUT VCC enable_b +-- Retrieval info: USED_PORT: q_a 0 0 16 0 OUTPUT NODEFVAL q_a[15..0] +-- Retrieval info: USED_PORT: q_b 0 0 1 0 OUTPUT NODEFVAL q_b[0..0] +-- Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT VCC wren_a +-- Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT VCC wren_b +-- Retrieval info: CONNECT: @data_a 0 0 16 0 data_a 0 0 16 0 +-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 +-- Retrieval info: CONNECT: q_a 0 0 16 0 @q_a 0 0 16 0 +-- Retrieval info: CONNECT: q_b 0 0 1 0 @q_b 0 0 1 0 +-- Retrieval info: CONNECT: @address_a 0 0 8 0 address_a 0 0 8 0 +-- Retrieval info: CONNECT: @data_b 0 0 1 0 data_b 0 0 1 0 +-- Retrieval info: CONNECT: @address_b 0 0 12 0 address_b 0 0 12 0 +-- Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock_a 0 0 0 0 +-- Retrieval info: CONNECT: @clocken0 0 0 0 0 enable_a 0 0 0 0 +-- Retrieval info: CONNECT: @clock1 0 0 0 0 clock_b 0 0 0 0 +-- Retrieval info: CONNECT: @clocken1 0 0 0 0 enable_b 0 0 0 0 +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.cmp TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block.bsf TRUE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_inst.vhd FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_waveforms.html TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL Altera_UP_SD_Card_Memory_Block_wave*.jpg FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd new file mode 100644 index 0000000..7b195b6 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Card_Response_Receiver.vhd @@ -0,0 +1,308 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +------------------------------------------------------------------------------------- +-- This module looks at the data on the CMD line and waits to receive a response. +-- It begins examining the data lines when the i_begin signal is asserted. It then +-- waits for a first '0'. It then proceeds to store as many bits as are required by +-- the response packet. Each message bit passes through the CRC7 circuit so that +-- the CRC check sum can be verified at the end of transmission. The circuit then produces +-- the o_data and o_CRC_passed outputs to indicate the message received and if the CRC +-- check passed. +-- +-- If for some reason the requested response does not arrive within 56 clock cycles +-- then the circuit will produce a '1' on the o_timeout output. In such a case the +-- o_data should be ignored. +-- +-- In case of a response that is not 001, 010, 011 or 110, the circuit expects +-- no response. +-- +-- A signal o_done is asserted when the circuit has completed response retrieval. In +-- a case when a response is not expected, just wait for the CD Card to process the +-- command. This is done by waiting 8 (=PROCESSING_DELAY) clock cycles. +-- +-- NOTES/REVISIONS: +------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.std_logic_unsigned.all; + +entity Altera_UP_SD_Card_Response_Receiver is + generic ( + TIMEOUT : std_logic_vector(7 downto 0) := "00111000"; + BUSY_WAIT : std_logic_vector(7 downto 0) := "00110000"; + PROCESSING_DELAY : std_logic_vector(7 downto 0) := "00001000" + ); + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_begin : in std_logic; + i_scan_pulse : in std_logic; + i_datain : in std_logic; + i_wait_cmd_busy : in std_logic; + i_response_type : in std_logic_vector(2 downto 0); + o_data : out std_logic_vector(127 downto 0); + o_CRC_passed : out std_logic; + o_timeout : out std_logic; + o_done : out std_logic + ); +end entity; + +architecture rtl of Altera_UP_SD_Card_Response_Receiver is + + component Altera_UP_SD_CRC7_Generator + port + ( + i_clock : in std_logic; + i_enable : in std_logic; + i_reset_n : in std_logic; + i_shift : in std_logic; + i_datain : in std_logic; + o_dataout : out std_logic; + o_crcout : out std_logic_vector(6 downto 0) + ); + end component; + -- Build an enumerated type for the state machine. On reset always reset the DE2 and read the state + -- of the switches. + type state_type is (s_WAIT_BEGIN, s_WAIT_END, s_WAIT_PROCESSING_DELAY, s_WAIT_BUSY, s_WAIT_BUSY_END, s_WAIT_BEGIN_DEASSERT); + + -- Register to hold the current state + signal current_state : state_type; + signal next_state : state_type; + + -- Local wires + -- REGISTERED + signal registered_data_input : std_logic_vector(127 downto 0); + signal response_incoming : std_logic; + signal counter, timeout_counter : std_logic_vector(7 downto 0); + signal crc_shift, keep_reading_bits, shift_crc_bits : std_logic; + -- UNREGISTERED + signal limit, limit_minus_1 : std_logic_vector(7 downto 0); + signal check_crc : std_logic; + signal CRC_bits : std_logic_vector(6 downto 0); + signal start_reading_bits, operation_complete, enable_crc_unit : std_logic; +begin + -- Control FSM. Begin operation when i_begin is raised, then wait for the operation to end and i_begin to be deasserted. + state_regs: process(i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + current_state <= s_WAIT_BEGIN; + elsif (rising_edge(i_clock)) then + current_state <= next_state; + end if; + end process; + + state_transitions: process(current_state, i_begin, operation_complete, timeout_counter, i_wait_cmd_busy, i_scan_pulse, i_datain) + begin + case current_state is + when s_WAIT_BEGIN => + if (i_begin = '1') then + next_state <= s_WAIT_END; + else + next_state <= s_WAIT_BEGIN; + end if; + + when s_WAIT_END => + if (operation_complete = '1') then + if (timeout_counter = TIMEOUT) then + next_state <= s_WAIT_BEGIN_DEASSERT; + else + next_state <= s_WAIT_PROCESSING_DELAY; + end if; + + else + next_state <= s_WAIT_END; + end if; + + when s_WAIT_PROCESSING_DELAY => + if (timeout_counter = PROCESSING_DELAY) then + if (i_wait_cmd_busy = '1') then + next_state <= s_WAIT_BUSY; + else + next_state <= s_WAIT_BEGIN_DEASSERT; + end if; + else + next_state <= s_WAIT_PROCESSING_DELAY; + end if; + + when s_WAIT_BUSY => + if ((i_scan_pulse = '1') and (i_datain = '0')) then + next_state <= s_WAIT_BUSY_END; + else + if (timeout_counter = BUSY_WAIT) then + -- If the card did not become busy, then it would not have raised the optional busy signal. + -- In such a case, proceeed further as the command has finished correctly. + next_state <= s_WAIT_BEGIN_DEASSERT; + else + next_state <= s_WAIT_BUSY; + end if; + end if; + + when s_WAIT_BUSY_END => + if ((i_scan_pulse = '1') and (i_datain = '1')) then + next_state <= s_WAIT_BEGIN_DEASSERT; + else + next_state <= s_WAIT_BUSY_END; + end if; + + when s_WAIT_BEGIN_DEASSERT => + if (i_begin = '1') then + next_state <= s_WAIT_BEGIN_DEASSERT; + else + next_state <= s_WAIT_BEGIN; + end if; + when others => + next_state <= s_WAIT_BEGIN; + end case; + end process; + + -- Store the response as it appears on the i_datain line. + received_data_buffer: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + registered_data_input <= (OTHERS=>'0'); + elsif (rising_edge(i_clock)) then + -- Only read new data and update the counter value when the scan pulse is high. + if (i_scan_pulse = '1') then + if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then + registered_data_input(127 downto 1) <= registered_data_input(126 downto 0); + registered_data_input(0) <= i_datain; + end if; + end if; + end if; + end process; + + -- Counter received bits + data_read_counter: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + counter <= (OTHERS=>'0'); + elsif (rising_edge(i_clock)) then + -- Reset he counter every time you being reading the response. + if (current_state = s_WAIT_BEGIN) then + counter <= (OTHERS => '0'); + end if; + -- Update the counter value when the scan pulse is high. + if (i_scan_pulse = '1') then + if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then + counter <= counter + '1'; + end if; + end if; + end if; + end process; + operation_complete <= '1' when (((counter = limit) and (not (limit = "00000000"))) or + (timeout_counter = TIMEOUT) or + ((timeout_counter = PROCESSING_DELAY) and (limit = "00000000"))) else '0'; + + -- Count the number of scan pulses before the response is received. If the counter + -- exceeds TIMEOUT value, then an error must have occured when the SD card received a message. + timeout_counter_control: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + timeout_counter <= (OTHERS=>'0'); + elsif (rising_edge(i_clock)) then + -- Reset the counter every time you begin reading the response. + if ((current_state = s_WAIT_BEGIN) or ((current_state = s_WAIT_END) and (operation_complete = '1') and (not (timeout_counter = TIMEOUT)))) then + timeout_counter <= (OTHERS => '0'); + end if; + -- Update the counter value when the scan pulse is high. + if (i_scan_pulse = '1') then + if (((start_reading_bits = '0') and (keep_reading_bits = '0') and (current_state = s_WAIT_END) and (not (timeout_counter = TIMEOUT))) or + (current_state = s_WAIT_PROCESSING_DELAY) or (current_state = s_WAIT_BUSY)) then + timeout_counter <= timeout_counter + '1'; + end if; + end if; + end if; + end process; + + -- Enable data storing only after you see the first 0. + read_enable_logic: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + keep_reading_bits <= '0'; + elsif (rising_edge(i_clock)) then + if (i_scan_pulse = '1') then + if ((start_reading_bits = '1') or ((keep_reading_bits = '1') and (not (counter = limit_minus_1)))) then + keep_reading_bits <= '1'; + else + keep_reading_bits <= '0'; + end if; + end if; + end if; + end process; + start_reading_bits <= '1' when ((current_state = s_WAIT_END) and (i_datain = '0') and + (counter = "00000000") and (not (limit = "00000000"))) else '0'; + + -- CRC7 checker. + crc_checker: Altera_UP_SD_CRC7_Generator PORT MAP + ( + i_clock => i_clock, + i_reset_n => i_reset_n, + i_enable => enable_crc_unit, + i_shift => shift_crc_bits, + i_datain => registered_data_input(7), + o_crcout => CRC_bits + ); + enable_crc_unit <= '1' when ((i_scan_pulse = '1') and (current_state = s_WAIT_END)) else '0'; + + -- Clear CRC7 registers before processing the response bits + crc_control_register: process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + shift_crc_bits <= '1'; + elsif (rising_edge(i_clock)) then + -- Reset he counter every time you being reading the response. + if (current_state = s_WAIT_BEGIN) then + -- clear the CRC7 contents before you process the next message. + shift_crc_bits <= '1'; + end if; + -- Only read new data and update the counter value when the scan pulse is high. + if (i_scan_pulse = '1') then + if ((start_reading_bits = '1') or (keep_reading_bits = '1')) then + if (counter = "00000111") then + -- Once the 7-bits of the CRC checker have been cleared you can process the message and + -- compute its CRC bits to verify the validity of the transmission. + shift_crc_bits <= '0'; + end if; + end if; + end if; + end if; + end process; + + -- Indicate the number of bits to expect in the response packet. + limit <= "00110000" when ((i_response_type = "001") or + (i_response_type = "011") or + (i_response_type = "110")) else + "10001000" when (i_response_type = "010") else + "00000000"; -- No response + limit_minus_1 <= + "00101111" when ((i_response_type = "001") or + (i_response_type = "011") or + (i_response_type = "110")) else + "10000111" when (i_response_type = "010") else + "00000000"; -- No response + + check_crc <= '1' when ((i_response_type = "001") or (i_response_type = "110")) else '0'; + + -- Generate Circuit outputs + o_data <= (registered_data_input(127 downto 1) & '1') when (i_response_type = "010") else + (CONV_STD_LOGIC_VECTOR(0, 96) & registered_data_input(39 downto 8)); + + o_CRC_passed <= '1' when ((check_crc = '0') or + ((registered_data_input(0) = '1') and (CRC_bits = registered_data_input(7 downto 1)))) else '0'; + + o_timeout <= '1' when (timeout_counter = TIMEOUT) else '0'; + o_done <= '1' when (current_state = s_WAIT_BEGIN_DEASSERT) else '0'; +end rtl; \ No newline at end of file diff --git a/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd new file mode 100644 index 0000000..7529de8 --- /dev/null +++ b/ip/altera_up_sd_card_avalon_interface_mod/hdl/Altera_UP_SD_Signal_Trigger.vhd @@ -0,0 +1,57 @@ +-- (C) 2001-2015 Altera Corporation. All rights reserved. +-- Your use of Altera Corporation's design tools, logic functions and other +-- software and tools, and its AMPP partner logic functions, and any output +-- files any of the foregoing (including device programming or simulation +-- files), and any associated documentation or information are expressly subject +-- to the terms and conditions of the Altera Program License Subscription +-- Agreement, Altera MegaCore Function License Agreement, or other applicable +-- license agreement, including, without limitation, that your use is for the +-- sole purpose of programming logic devices manufactured by Altera and sold by +-- Altera or its authorized distributors. Please refer to the applicable +-- agreement for further details. + + +--------------------------------------------------------------------------------------- +-- This module generates a trigger pulse every time it sees a transition +-- from 0 to 1 on signal i_signal. +-- +-- NOTES/REVISIONS: +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity Altera_UP_SD_Signal_Trigger is + + port + ( + i_clock : in std_logic; + i_reset_n : in std_logic; + i_signal : in std_logic; + o_trigger : out std_logic + ); + +end entity; + +architecture rtl of Altera_UP_SD_Signal_Trigger is + + -- Local wires + -- REGISTERED + signal local_reg : std_logic; +begin + + process (i_clock, i_reset_n) + begin + if (i_reset_n = '0') then + local_reg <= '0'; + else + if (rising_edge(i_clock)) then + local_reg <= i_signal; + end if; + end if; + end process; + + o_trigger <= '1' when ((local_reg = '0') and (i_signal = '1')) + else '0'; +end rtl; \ No newline at end of file diff --git a/ip/i2c_opencores/Docs/I2C_tests.c b/ip/i2c_opencores/Docs/I2C_tests.c new file mode 100644 index 0000000..045d2ca --- /dev/null +++ b/ip/i2c_opencores/Docs/I2C_tests.c @@ -0,0 +1,99 @@ +/* these test were created to show how to use the opencores I2C along with a driver found in + * the I2C_opencores component to talk to various components. + * This test example uses a littel daughter board from microtronix + * it has a I2c to parallel chip (PCA9554A) a EEPORM and real time clock. + * I chose not to impliment the real time clock. + * But you can see how the calls work + * There are only 4 functions associalted with the I2C driver + * I2C start - send start bit and address of the chip + * I2C_read - read data + * I2C_write. - write data + * how and when each of these get used is based on the device you + * are talking to. + * See the driver code for details of each function. + * */ + +#include +#include "system.h" +#include "i2c_opencores.h" +int main() +{ + int data; + int i; + // testing the PCA9554A paralle interface + // this writes a 5 to the leds and read the position of the dip switches. + printf(" tesing the PCA9554A interface the\n the LEDS should be at a 5 \n"); + // address 0x38 + // set the fequesncy that you want to run at + // most devices work at 100Khz some faster + I2C_init(I2CA_BASE,ALT_CPU_FREQ,100000); + I2C_init(I2CA_BASE,ALT_CPU_FREQ,100000); + // for the parallel io only the first 4 are output s + + // the PCA9554A uses a command word right after the chip address word ( the start work) + I2C_start(I2CA_BASE,0x38,0);// chip address in write mode + I2C_write(I2CA_BASE,3,0); // write to register 3 command + I2C_write(I2CA_BASE,0xf0,1); // set the bottom 4 bits to outputs for the LEDs set the stop + + // now right to the leds + I2C_start(I2CA_BASE,0x38,0); // address the chip in write mode + I2C_write(I2CA_BASE,1,0); // set command to the pca9554 to be output register + I2C_write(I2CA_BASE,5,1); // write the data to the output register and set the stop + +//now read the dip switches +// first set the command to 0 + I2C_start(I2CA_BASE,0x38,0); //address the chip in write mode +data = I2C_write(I2CA_BASE,0,0); // set command to read input register. + I2C_start(I2CA_BASE,0x38,1); //send start again but this time in read mode +data = I2C_read(I2CA_BASE,1); // read the input register and send stop +data = 0xff & (data >>4); +printf("dip switch 0x%x\n",data); + +printf("\nNow writing and reading from the EEPROM\n"); +//address 0x50-57 +I2C_start(I2CA_BASE,0x50,0); // chip address in write mode +I2C_write(I2CA_BASE,0,0); // write to starting address of 0 +// now write the data +for (i=0;i<7;i++) // can only write 8 bites at a time +{ + I2C_write(I2CA_BASE,i,0); // writ the data +} + I2C_write(I2CA_BASE,i,1); // write last one with last flag + + while ( I2C_start(I2CA_BASE,0x50,0)); // make sure the write is done be fore continuing. + // can ony burst 8 at a time. + +I2C_write(I2CA_BASE,8,0); // write to starting address of 8 +// now write the data +for (i=0;i<7;i++) // write the next 8 bytes +{ + I2C_write(I2CA_BASE,i+8,0); // +} + I2C_write(I2CA_BASE,i+8,1); // write last one with last flag + + while ( I2C_start(I2CA_BASE,0x50,0)); // make sure the write is done be fore continuing. + + //now read the values +// first set the command to 0 + I2C_start(I2CA_BASE,0x50,0); //set chip address and set to write/ + I2C_write(I2CA_BASE,0,0); // set address to 0. +I2C_start(I2CA_BASE,0x50,1); //set chip address in read mode +for (i=0;i<15;i++) +{ + data = I2C_read(I2CA_BASE,0); // memory array + printf("\tdata = 0x%x\n",data); +} + +data = I2C_read(I2CA_BASE,1); // last memory read + printf("\tdata = 0x%x\n",data); + + + + + + + + printf("Hello from Nios II!\n"); + + return 0; +} diff --git a/ip/i2c_opencores/Docs/i2c_specs.pdf b/ip/i2c_opencores/Docs/i2c_specs.pdf new file mode 100644 index 0000000000000000000000000000000000000000..72021df117397a4c324ee17a0515db6f04af5a93 GIT binary patch literal 211471 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

$!*8+!jWjT$ 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⋘^_5TbYiv8GgfB!s{U43V^y5Q-SkQW$>}Iw;FT zCKwC|j4jX(wr;D+KBUnyiB0N0y4Hhgk)~>k*?X6y(yD5*{k(T)`((e*^ZW89P?gcE zN4w8AOCBZwCd%TXQCO=Dxhk?*E?P@$ZWkRBaSG~%NWi?!cSX1+-DBPW3(cPjnT%~d?}@L#h#1xD?^I) zHUfVj9%u{vzWN?x8k67`!uwSp2=B-4N*@bl0hJF*ltZJ^2yl!!%oC#ZhIteW)z$>1 z7QUUwJa6{aNR^ddOqnS+^3(p5U-kFMdJHDB;ivv?~!`4|C%Xh?j-=u2^>?%nAkF;B@t zk$6n^jDnJ;284K3z!#Ooc$Jt2AwWv3x+V=#hGgB@<_!;{){bo|%@X?I=NltzXg+Bn zhd?830)k=P01d!^21ofz7*>NuJ=u$jGCm^4h%oCONhDx_(*g0x%=C|lK36bApW)NX zzd3mC=XC=Mvrh-t9$m7#BfSjoC~XM?*!a z&$Nx8!iz*St;QdRPV*5klsRApIqHS2um=vJ*QlR4|BNg~r;5G;hUJvusBr?{QIk}q zL>mx0PEneF=|@Azh@Pe>yFrdLah{|HBMd&+So?*;T?&9 z`z7%fe=A{V6~3FmKCVjX6$}=zM8)W0)CqmKPuKxF@MdmvXlvy8=sp+;9ZQ^rv(YQ! z^~58=TNc_4`-R=H6rIFpfjmToZrOtTnev`?+S?yv)4HY&d8> zX~t&6j0Z9ka7cC5OTl0OI~@)ZBPn-S%LJWSZBZX@&!X_TFm5NN2!}7xIZ$)`xjQ*S zE<@?aru2QFbYxSJO0SM=uYS?1Bis9WcJ);~9?h9w9oBSVV5+c5mNir-XHcD-MfI$C zDi&!1>%u@%)>2ZnpDxZNB5*hQeX|ir9-&P;e_EIFX}C|+u{;+|@X0jPv7{)G+BD*Y zRH!};Xl}BGhhczB)qrlfuA(T(K{hQ1J-krSC}}yVLKjSO`0x_ln4+CTB4I`uiQSUr za2RyR|36AFYq<&PXGwu@f@y8(wNf@6va@tRT$(p8Bt=iZ3p9P+P z<*i#MUd*q-+c7|C>;FOyU@_1KN(GgC+6W5YPI`F zEjYo6tp?;YN+@oU+o2s>T=@xDq~6KR%lQqAvB%d_-Q(|J%1m~X1J&Hf8wag}_Cd#1 zXFuD|^(XsNqtqVjh<(Jd+c_eS8OPGJ+n%;(?Ac&Cm~-K@DS-^f4ASA3P4$DlsUoP+lO!!7{0 zh9(Scsy%zWF2Dr)IEH1f1+^=g>f;rJJeq8d3Y*O#+iDy}(V{P9JWP`WB-I&ssltNC zL1iNu08RvP0(g~9x+Y!tz6(OGbFTX?gKGkhT;ax9nI?$VKERz&U{ZOYJR;JjF3zgT zd*sA`l#r4lf@f5&!y?oOi@-NC?uCN9iIC;MRB@V!*z`bSQl9Z1x^8LFfD|&-vO~)R zi2h`XjC7HtLhYyk^rqr0wdRDB*&~V8T1y(motmh5NHM3#X?enyMpj#`9HWWEIUVtu zsGGT@<4Q_jY8 z%BkDKmEhtP%ty++WaO(@tZSZ@F(PGV-j!zY%$UbSK@_u@T)JN4EsrR&z;h@|%e_ISy%$Vjbn zw78w*cFWK?qL&j`QvH-g=Q)c`X%?O5ERm{8PG&WJbZFl|EY0??Cs`wV4NIu<(I=`^ zW5G(D|0>DdFNVHe@X0g@4O0b;@K{2y)~t4e3sz@_Y_R+x-K5jvl-?PnTC?Oe_tsx@ zt25n1tPA}P{f?Fzi7WB&qSgcc3p}K`bEL2OcF<)oW7~q^HV)i<_WV% zo0gW|>Jah`|DKw&;zpapv%dSkjF)|E6XzYr?>XPA&#}*E`)uDi_T4%6;yCu5!3JNT z_&i{xgtlRgL<~!ZG*X4O8v!u}r2({#QmRR1>x&B0rtS}*iKdPeng*COq=~K4n8YSk zLi=M16Qf8~rA%YhC?whQoWqMWO`1=Bp7V1TD}L_x`F+1%unO%ew=hFa!d)$cSI%P& zj2+!})j{z?>GEf9K+IGvs+Zb8?TZk4UN@KImzZnwYt54;T`*k}?{{`{`y(gJ-k0b5zb%;WLj8><7L6ZFcbWNkiJ7Cm#&pG4FIE0f^{D-Od z4^#0UrlJYL!5G*P12JE_VqtVGmPOZMY5VrW{D<n7}eCgic=BY)Vsn;3FD(is89l2Q04U!W^p=76`*Z?pz}eDLKd-| z2wCtTfyF6bcMPaCj|Q{2&)=c~1^xtPmi8AD8^5^n*PD*A_Q|FA`szSex^u%DBZvR| zBvc&I)b-W5opXP=a{U)4e$e_CE{r{;>$R?3bCXYB*|mQ6N7r!upwa{DK!B<214I`t zoC`*%96pKTs|N$DCMU?#)Hpqn zI4zPtrH@692`9v3D!DzeExDW67d)hro5fAZes!4IPLo^c7PBSzY`B#mJ+&Vj2y7ys zp-4ro67|H_u_wZ$P8Dd2u@aU@LIQ?otN={PfM|l}6tSUiK61&BKNOz#0D2Jhr z(@ZXmBmRc?xyzR?!?ZC3ySD4fUK}HVj71W>90@b<=3Fu>=cX5qcu|q26o#gu8;V0W zKvEPc;F_3(pOU!m~09-t;t)aap542a43Qi34z)6T_W<$Z&GB5G)OEJp zwdDDGe-A`=mpW@4Yzn9o$qU!%F<60aAlt6JDHhZVMm!3u&x;5yZsHl%kqJ(~IR>*~ z87AF^Ux*J%G0jpPbchMEbTH^pE-i#pF*gL?GAcxdt-|>bnlo_rZo!jfY|UQJwunLY zG)oy&k?G;AkQK9}g4}JHm1UGGRh`GFHFO`hP9C5J=|QFy91IOggU&!@JGG5|ksFal zv#Do>S zvcqNwF52E%Szu@maExmTsO(|guk;HamA-FSQ0e!unGD0S!3^|W*(`%m5QLZ%mt&S) zkS!quzs1ZNvguapvOB#ndRFFw%JjkxFYYk365=>bhIh+SCX;1@K}1JF&cKC?-N`VT zW5*rGu23|Mu4J4F{8)(zre(RVfZ<#)$S^d!;^)-K3VdcCdbJ8_F}?oe86~IcR1Q^+ zRRT{}zE#;;8TCKRRAwtoS`#{yU{meC-PGWvW*10o-*)Nj5l)m>K<%w^d)Vy_)_VFc07LyoZ`pTacw+* zsx)q2%wN7gsf!ebQ=^65?ghRUTGPswd0D zB7qtqHN8UADC1E~EfcbiwnCODi9uT-8+8L==p(o|p-s52L49S#1|?Ooc`eFoLIVRO zp+WJqOi2p-7PDkQ2phe!O9DbB(?Uv48yfmnd%0XMX*{oiQXGI1?3@CEZIxoj6~!*A zQH<~hptoLh$P{5sJ!91*Qwni5^j5|J{_{DH#;*dKA#E9`u&zm1tEE*}GXhb@Rw1owyJ`|>-6mKo6=(*@nAH4H zO+ph=Rnckt1GGtqKc;16QaZ8GIQzbHTCpz9-S_VK-TC|8_s8e+xzb?zz+82is;tm2 z?^`a#>~JV%R8!1ec*zyF8Lt@ykQ9toGe*s9{$F_g@(YtA z22;%aa;yjAN08X-t<9>9P)We_F{FdDl=-5Usa2JknluNC5ct)0b5`Mx)kcQiYM7%Abr!twX*vfnz z?-llk_9n(M$NA&J@x<}=iA)7o_!(g)QE9Ja&b7ad-zMiXAGUnb@|TQuik}r`6ATte zGp-53a7=3sqeQA1)udraZD|g*#neCmWUdd=UvM~Rc|_w0xJ#(9Ksq6090?&FQ@OB= z5ekPxR7wUK7S{eVPbCIitk^P!URZ8h2}Ui4NNgDiW7ljY`K}hHyP(wNw0I_N#mC|k z@k;z`T!=4_H{VawqG^;@%0?4tjAE0zt~4I48`=oyG0Uz~L3SN}uwt$kknu=~)UIpI zXTA_C#0jL94Lg&Q2t)^-!n70?5l7o76ar3Aq@gF3rm#eLAvH9iFH0uPQJT1v658kj zDD)LYO4IWHum_~dNBGZ8O^0?AtBb+dj^yeRRjAb;J(hml7bE?l^yntsjGe`nd>*hS zwdcvz)#|%n$W{C`(tD_@)v4>rWZQx2HvIDgsbI2^W?2(L?5`oqJebTY7N|P9zfXCa zx_jNdazFRD`!qXOcTHS$FUq2hN6;2L;ylDYC5(H&%T5Us-qY+!q2j%WE;@f%_W@eK zA2=84d~O-Ck7F3#!|^U?e^Jrt1O6k*4kt!1Dq?Ygv8=4a>1y?O5UAQ#NEy+g@fqIY z&+#nZl=haqqh7}A>C$8@zv^gIywj0mWoU{cE8Bt9gQ&b$mT7ReuhRIg7Ug>i4R3&k zcQ$1}ND;)@9+7XzH)zlxUIr!b^GJqJKBr9{di1qLibGSP4?I*MTSdbfj$WOe(SAVLre@yRt5$}YZyih$##<^oiKqoBK z5-}1)hUH=mkp(^m^(zJfO$?=8R*tDLFotsI)}EZqXv_ptVb}_DmLcaE%*=B9C5*?& zI3WP%;sWk`Kl1T@d-0RS?XXzjSySNg$d+&Q-}_<@R*QCa(}m)QC*p^Lj8_NoLiG-g zR*wpJ^xr=NKett%A&l+kjMZj|=S4CuV(^p~Vi?IB8zYQTf(U`T7?VppS96vcD+JDR z8aKgJIJUx_<;ZysbF&%r9wG?*{2lH@5wr^m+;+9Rz2+u(HX>6`%a6EP^K`Q81vhhW zYy&?B!OuI~u?N*r{t&`zpH{cBO7$(oAZ-y5CT`UsH-qvV!AIDELDi5yE6OX70?Y6s zcn7OIyv?>&x9&pV&CuF1GsnD#y3i(OsK%Qttz^+IQnF~r@iz-8-QjYP-MU0abtGkL zSfr5M*#mi|-WKnv#vi>QG?=%Hn>YMy`Z7!5Z>k-at-CS_4E~nHa+1w;yNYHIA>h$T@5E2NVs&c zM8+Li)Ll$%=;*!8i(&{TJQNIuEpRPDlw2B0lJ<(C=ARRf_w*_XaGT)tO{9nQihfpSE&aYuDmvC>I!V7y`XH_Skgs9WzkrWeq2{#NDOmNU zCX5LcfsqA#U%+Dm7Wy{#eMdD$WSXH<#`fivWkX&yXu1|xjdjr?|EmnywX%A*EH6)% zmZyM<86LA%dFdJ^Twx>(h_DQ?s?}cKv^9|17;NRdJ-zu}!ix^4gYc247A1VnWopRN z;te9j>kiiiakO+#d^ zxQEgyAYR!nGVtTJ{HB91g*N=*?@#P3=`oUy>FG=7UL4sNRGa~~EcuHQhdT@SjpS(m zp5Eb^XFZKSINI0Q|GhnJbBCkRWFghn-LdEFhVWy?sp^fB8+}4uvG?`#?t4X6!&T&w)cA&yqCOlz6*Nl10l>Qy0u@7e4_qG?8l>w=fOO^hl_t)qeGGu(>-=WfWlv*S2x#x?gM_Gt6cc|rl4S|1 z@2r=2f&J&!w0iTY-#)>JM9IUv35c_h8!5Aqj#djGs>LLd3Cbb41H*mEp z97B4G#M=+OH<4J zehRu3i_ zY@hmrz?gq5{8N0KJDEI!e-0UN zBtS5bj;H`P11|Dr(d3Y+n1COo*ubHKxSG74%&Hp-)6G=?Tn3C$rVy}+Rp+pBk1bG_Agyc$09;fI{zab z^tdnx+-PfS!)*{SC~Oc&b|v?Pvr*8!vw^HbQL>mu8-*%k=~qfc@UR6CE5KGUxrA$N zK@4k9U&=x`Rl8tC+xYI(wcT(13**VXzg*V1I_`HTlaFnC^jpV9w|sMD3x4LzM_9ah z4a)~M)Mjc!I}-8kEys@E>u7ozX5V@Lmf!$|N}x3N#3Ht8Gd4w5y%=Vok}3dWU_*wk zF~QQ@29+g0#gpNoKr`5{;p!JQgQO9rJ&f4<{NIsIjT%~dLZ#BB1Z=0w^#_6|1uw3# zk!Oj6Dpv*$yqGX&wPG(9OVrPmO4rR24kk#+#mo{2&5VD?NBeT-g<=W(W zQ}|iK(F`eN<}J=JkYT zhV-S{+E`rgOh7lc&=_K?mT1I{jS1eJKyK4x(14+a@>)?lsqqPIOyjiM^}QmD^>kfR z3oXxewTc~09Xl)f2q|M>BnR1-ejo{hIF_kADoh`d@=zwLYb`-qnyQuR4P*&$sv{`_ zH#i!ZFye|N=GrL20pA5YQpkZngF9D@SOp_)eW;8TJFaphTm4Pkml)+T=PekBJ_X_7auFKhz*vM^kZsA6_(ZFcrP~f=pxNAx}Y`bnhF{cnY6mo4yAuo+CEP5HNnEpZK)NaMieyVL6KO)4 zlSJu+91_qd#TDOZtIe`4_sTqy71@yac^S)eBu-dMxg*}Om|S2BuwkJpE^MLix?Q0ITwV^@|cMMF52yNs^-QYolLoQhUj(aOEWmaEcoRa#EgvSnvBq(rh2!=LrS!KC0TDSdEo zFd$aZ9JI1((ZN*eU?~&a3*w`}Cf4B6Q`=cW-}o_VC4pz4+%2C9-uz-)?U8 z)t6q{`rY8@-!T5%|)QC#fDYB4Uv;5VKs(hH=eyGd8m8(7w*{ zwJfI_A6U>0dVG;@w<51{OE#Jv^de%qw@OwOt!vfBvcba437#Wwwoo_2| z`zO*)MFgE1Y8bM(m?TferGrcGWSmU#lATD#$KxNwxwyY3RfVly1uM-B^{QW#h)V&0 zPvIv|AAk+-6!-Zl++a;%#rD?KW7X$Z4*Gn!hJy8U{{Ku@eQXow8Nb(OpW}-^&L45k z&L#FGceWGf96Ry(BMJEOK}H=y0t5nhp&6|-wbK;G5^Um+H7on-CNu8y z9|dF}bfaWbRH>6v(Ei|`iI!EU+8<;>U4^Et345N`PKD!p-{+q9!}nf(zvuTn3u)R9 z4%YiZq24Pg+8cgJPFI}-A^xJX>|Ar+b8^l=@B1vrTI(6qd>xcin*d!}*$zYZ`TU~_ zs89jKXsa?@*n-LyUIf)2j~ey)BWg=T^~WS8>Qf}rP#u&S1};dF+&)0sK#Qyc+%mem zOCNv|kk)`SW2z@iQ2DhCw2;e^y8F=9gYMX9;M%pL*Oy*7I+*Tg9VmuEk%S>VX7_Df zUheEwl-T%5)A7B-Z+viST+4On@^`)7)VJ@C?gjWUyS69Tze7$w#Js>9V^@sVJ^q;!kN`ExDR=QVuSb9=w3x-<;1l^Yjl`Ow&DrO38jGxWO#Wp4|=5Y%y zr^DXN+iYI1&(^f85|6t2?30=YbV$X2htFQX-e~qT7cQ#rsdrRXT_x{cKN??#Vhg4k z4xH<`D8DD)ky*L1hW4;ThPj4VEs~-E-l74nVlPssIO8L}RnlZQnhY0g(4=$c$H>?! zn=2(5xDYkr+i^YcRbM zBh#^RY%O*#W{x>=CJcR9L$ZVMFT;bOB6ccVN|ub$C3xGG5-ydR?dg(pg8k zRM<~k{<8lrg!$EHUl?v&=eJ`@;HS^%Up3t}yypv~kV>*MtZ9ZN3@flE7GGkZJxzPq zmBpXO1R0H+ct-Y>_o1TWuf8G1<4=(g5XCnuTh!Q$R~`xRrKj{JUctB@UlJZc z)&`}lu-TA` z7r`FBlxb%s=LYvEy42n(5=%twPYtBfDV7_FOh*!GPvnR?D-mg^Lt-ZNsW3B23SnlK zr64gg+LXi`jL(M2xHut^!_hg39GPn$Y=h}-L(INZF-#_ldd4t~g&}_LHV;c=f8PO# zIn;e1%OOw|N7GdgvSr5%%jLHQAsoSgaFvo1y4Q!aJcHBb<;5t zfy5Kp4|;4)(mC4doq!T7k+0xU|2;rW;gL{4U_{OEP z3xA0_Sx=1lp0pHS9#7BgJGp0I z`#*ij!Iy8>{xFcf@DH-T`>kU?TQ@A6tu@G7xV`1&8@@>1=MG!Vti|RiA6$Crmvj9Y zQB+55FNIQ}t`nx8o<8&L+-T*@#p9!2{czx@npAebwm0qfn?dXu2Lz>mLlu`Xtu!>T zJ!c?c1>Vh50pvvm@5LbAh)|?aMu73qpp~8IM2LzJRLKxJB63=fYD6~M?WV&r-9y$y z+(TP^_TL(M!FXE30d0q2U_3TlRE+6<8iDF-ga?WBz@@?!gDc9UL2zBVVS}}LhKah{ zd(Bn=bzdLWfS|UI9|I^Gbs$Yvh4l~nh4pydvjK(S`g1km(X}=U;x?l%XY}ZNZUORTm+Fcv=c+mLmE2nHUXG1(WG1(eE2GQEk#LjP z-QiwkU52|;>+XmaJNfPoq1YvNcSKfMr;+H=qluAphdxfi(F{XR3F(yEE${(Ru~m6; zg(oh)%wOd1@@5`Gl&UeZk_c%t+JaWr%*$F;GhNXLD3!LR-P6q4LiRFLg~C%zBr&7h zs`sGB$V52Husffp1tGqC8Y+B2$5kchP@Xl+MX2GUYtUaBzj1VUFFr5SY? zX^0x_Z)kKDM4A?boRyY@;O)<5cAQWtlBvblNA{Q7yiPu8Z0~L{`gt}qo=m-3Y{^e- z5AN#niLOwvrO!z`mN&Ofp4oHco5t_A|1=jCB}Iuwg#Bdv?Gt_J>22vmBBUr@K6ixO zRj(QuNXLhvu>xP3nNHISb;jIc6p(>-gtNy%;qH({M6xU*vSqKx+CV>OBnRUm1-=cd zKO6?*;~O~J<`8${Js6+W8gzTOL$~|aDci!Uz<}0ic~O21SyL>KpUIgL(-GAgi}P35c2Tb;Q^X6C7d60hzYAPi=CtVT_E_4I_}va)%9$ zFx(~1gg?qKVY$=l#p69SBwT5;DP0cA2Zsq^@1T6ZlhyekBJnAIz;m-sA*Jg%4%BN) zc=iVyg^hVyhcu`Vs48SZDJxawlJZ2cgq0b^WMHG9T=w^;X`dUc_gb>vcd4{D5`kbE z2;wbvI=VYNK#OQ#B-|m7+XHrQ6^@c;m`=OZ>*1?5V#}ifUmMf0Gh79o{f^!42sjkc zi04K01v7)`sz_!;vLKels(49!B3i_2UDtj?>41;Di5vjo-K?jlpu2E1p+N?EB=`W- z=Sc;y-rqc=7d8lOpPtD<8_6Je)w_`^f3~YGwr%SQ z^HP7bbS;vWOiHpP(H3ommZKlrw5-^zsLZj`SW3LavZDfSjKM<(tXu2=Yda)Gy#Ygj zJp|rf`p}1T58EE+wdv+QbTfh?PYV`c8;0$n7_cI1nq&=z><3+{?3^RXanKPWd3f%< zNBlYG`@WOBT6)LtFGWkSbILjOT=FI5ym~(Qrr32iaX%?;b$usz!*xTxBi@nktDp8r zWwjhBC#Q^ZX->Z2|CTJ}#1X|9GKO=dDK@3}dX+jmtt=Vtl(NEB;Av`J$jd>B;(2CG4ZJE4XARcJI3R3BAE1^an;>tJPl<@T?%=lay*_$o)O*cqRmZ4 zu&4~Cxcq4w-q9t__(e!yzc-rZ9R9k^O`Nz1UixjSLXX6Xh(D0$TU>m=*)9GT zE^hEWF7lkNUyZOxELmbDASS`g<%Fz~-O27{Z)H7;S+e zU*$ei_FBiwIQD_h*MRqP;ld{Lm8%!nDs951unAK0Jwbu834_{99s=DAd)$GUY{>SiWKo;5~U_X^w3+Z zSUgCJr|z8K(!emga{3#UyLZ1bm^Y)(Hor97cc}TdXtvhO&ZT+-a?ptNj;KuWTzRzd zhuI#^!*S6t#O(B+nt!}FkPG@vll6x5arR>KR%0r{Oj8Z$17CI>y*l5grVweK0e+ML zX?ocYI_#(eIS@OBxtIAEVFn}2V1yZrqew#70OJ$VhrC089BC2(1B?&f#WmdXK7fM+ zyH5xKKm+1h7ns@2+hI77jy*lG&DkPnYkY%m^SAf| z?%{812S}$SzRELCXa*V{hG<7D^E9(`GUH-&V!l}}XJf%+Bz8z;s^`joE6Y=HViA|~ z=6p;05Q}*8uAd1juHUs;L~l^9&~Wfu=_-9%wO-A4@IH?p6h9w&92viHK0~uIh2mUi z)?8;6dYl2AHCLIh(7XyIN`(@oQVrw3RXgjd9e$~H0)X+E6UDhzKZdDhXnBT~XNvFv zod7zD3NC}|-#Y=2gmg)o>Gy zWT=J7kS|lL&{c)5Dph!nPbm2f<7^R|Ky(*d-5?qNpwVLSY!x{koz+eSf$<+2tyUXn z+l8a<9~HQB+TjrddghzuGJ-N>?@sr^(%D}NbB{k3j=`RTJ^%RQcVm%g1X{1w*64Hk zCw#XWpK7ixNbv^tN||o9-GG+Juo977@zJ%xqLnCs;RFV&R$~6dplT&_=!&kTGFBqL z>*~Iis#u9RFq~&o^>nSWl&H^2Rojxn*jHz7Ly_ZFreBQ+j3f`d zTw%Z8>U3O#CYQU1Qo|-6=x0HBFgSFu^(BqEL2MY z&%o%ZN&C#%fln<=U!b{s2{o1e0kZ>pgq%-l)A{izmaw9 zW1kdVczRNS;Af+UIXKq5SlG!vI;F&xl1*16V!Con!FR08Ag&M;2bgg7mZQ=mA7 zh+7d1VUcjQIs(~hNi;HAAZH=A`Ei9M^owR5fuyV8bm9Gub^i(oQGtCB_8}ZGWpm6I z8x;vlayj6{d-oI&$dDpWOXCChp&)?Z0a0TgHeSeSSjG5iy!8UvbOVJ}eA$$UJtaa4 ziBLn*M09E7(j;_gnmr-JX=a=paT<)%gQC~!z=efif-@}3o_HckTdH)Qb93-ms7y4dTe7kK^Y)^>W^dTrw&$>$Ib?6a)sF4mv2WSpj?LD_GL}9jHNR5rt6Pu}&EC>C%X8N`zwj(iF+K{eF zzm?q5uK2#wXN||rk)*X~tyvqEd&}Ckb}W}*DVAsOk96pqI>Ku#&$}z-=uE6?xG4LOkiRW6=8A#7txLj^FR@d}p6u?tFg9`Rv?F{BpL> zi4!|X>xPko6lfaSgjE_zThmY~&}c^zcOA4qV=-Fj#*|7-FjUl5+CYejrLESHb}P$9 z)=`zvZt9r2KeqjWx@F)Yq5iQBn(TSbcG_@-5`}q6&e#1Wt{{}9&7Fw^m z81Zi$taIHJzCUyTUT_`auSQwbD)i9m0K)E=3g<%?WYSV$(Alg;r148Pk^dh?DAI5l zpGW9%dXhd&pP(7~6OV-!EzdC&aR!uuA<5h*T(6iLYGv%{hEAk64V@UdZ}UlyGI&y@ z2fw;`^c>+?nI~v;s4Mfh1rCh{KK@&l$up}%+|Lb4W9mX0rgdpmLRx#;Ik;zz! zOEM`xAJm9ekTnRq&`e^{EZ`M1h*Ibja<^zi#DPxr0CMXOwGF_26Hx~Pqn3XUxrf=u z?epyup9t@f_Qag!F%*PQ__16u!C#7^BZMCMNp}hFG=>l@AU=Z(6K^w8J>9*%Eo}@F z3W}IX)Hz7v^8TIQx-@-h-y=`Izo}>EoyVSeaR1lup=OUhH~Zul)z`lJ*8Urh-_d{c zsrQ!ueEi+(FN~wmv2tU1J#`kbW)LN^t-)HR&%&x&;Ieq&7>p7p1tNq-WdgPa2ehzl z&XBnNwCUGu-PJHeUfbAFX;Y+qjC>YpYYUDX$bNJreZ6B0YuGAG*eXl_q7x}Ba&9$S zaP5|yuM6$`yl@@~Yu+ZdDXnLS!paw?F^B~YGb!OI$Mvm2)!EzzY>f-6>D1 zGuguyG{}3=sp#s}pv&E%5yUNYkx))m%EVL|AxI^QA?$Q8hpf$^(KIl{@TxBZlA|t| z$O82=j1CEM>Ykb5?`)lVe)7%rz3DRLgX()mqMS0sE~lKh6Zv2)3y?uQyucYbwdzDOYF>qU6IjmS#F=>}KntgVrZ+Tu5Cb81K` z_-(TOC;6&PU#m79sfyLej}cRYm_F6Eu&SMS?GJ)LN#V%P5p)ufLfH9+jR|Agpo}yt zc_<`Si#XxdP`>>?S1K%=Z#vOte~;tsQs}!Au4xzPLK{d7s?-)rznx%ljsLcV5>5VL zhfq9u8?UKqHuI&KMEeu@{>8=eEe{#BCQy9i3uJ+}NQ-}lX00r2%Yuqk&d!SmHd#WgQY-uGS*}Dh1rK@L3i5ZTafYzDL#-3>(nwtmKi3Rt z4Mzv}?%um2e-fJN9 zmI&K<>Y?LbiD3hWc-gV?5%~wiOBdbU;KeA~yc8|$&Pb5(`v(cXZ{VY{)9~QyhR!$T zhsTYyfYwsMja3u2pkYyu}EAWs4N>Y3DRv4j>-Q5cRQZ`ads)h zIZ^=?@<75In5T$y9djUC{;Z@#&P5ejl|hg-^yKhj$>+<@@f`Cpel94v^Bl+$6O_8)(| ziY`9H_~Ww9YCZN?JnFX|aD1JGp90?srFU$Urp-j|sE5Q){ha-iyp;%ahaw^804CQd zKYPQ4GR!0sC(I&yROSMJ_3`}USVN&|hb>q!wn^Z^QdKAN*yQ^$wHysV<}bLNCESf= zmC&1ZpRG{5m%UN%S9_cf-Y6U{>wS}$iZx@Ie<{f+fEUndPE^0G`O0A^Q3_D@;8KL4 zQS%U`xW<$roWaAL)iX(zHUE_hCgW2hHm!ey<0I$GR#f^6vM6NTbDeN%zQCzozh!%R zd(DjV?A*L~lb10w+b;80yOcCD4br6wFeLi|^-A{iRu=lDyM7-*1?B^ExwSPicZ*q~9nn#nRB8wbqSXcgCHa?4UICtnjn4|3#c@#f* zB0F8g0Ta#rQ#iXA(#y@G%;k1DEKFR*4-?7zO4hyQ8NHxTsyR5NEEIs5VzCP}42CkL z)1MaQ#dtOmG-fm>6Lf1dxwYc8}D9%94^)kC7xRthnH5>*q~*ud*iT5S@tzC zdXbm`Zh#q)$oedgH*@eTLRiYmMY-&#u*o$+#9L6f8c)8CBx2MK%8#&o?0iUc+&8M1 z@qmE(*bjP>KyfPz@gs1;ml~cNr!*e>THDqT#iMUpyrhAc5_~~}kKW+OuIe2R*$?XS z$Fk5YspO&@!(Ox-vlCNS-nP;5i#aW^GA)M-6$${d%jvGw4sFx209RAKtX1iGHj8w&AXblt5PvSRf~n>^|0U8i zpX!j_W$ck~K{@D0_r6m-s-GMrJx*r3m50 z_OI!r3{l4LhZsHv(lAgiA9Mjc5WlTnP_E%GB@(Qi>&f;}G4(NQ#2bVB|AN6I5`cQx zVK7;stgWh`vmS>+wYd7>O+jOHGIhe_j*NZOKTKWAWxB-F&&Tj*teM}MM5yx*!lV~U zBauV=@ae~#xba%*UE!6`;v)-)%~N||xz7WAi4GvPqCxcQ+18YKOl z2%=Nl8X`Dt;b++pA=_M2ncWj-&8Z*6a`o(Wc5vINS9GvrTc58&>%A*qN8>K#Vlx#> zFt}dTJjk`;<%=7IotJ*@2UCBhfkr=#lH_y(yQ+A0K{)0rqCzHePgH>d> z>z)#c_az}bs;ZhAtm05r^{9SLaTHkrX0gfT=+z9?IQOsKLOI%kqa}1QA|y!-dTB0X z6_bs4DXD_9=*sxHj;meY`0rLBj=qk8$!e~p>El|Cu0kz+uhDGzNt4$8_2gMbiYdk^17Pp$g)x7^IN})TL~VIjgP&iHCEEX|7m%|gf%>|gFy_8}?@9{9lNMF`HtZ_JOT^V;5GQAy zQ-K4X>kU5z_8GB5e`?yQ3i&^Uo!bLXf*0gJ@_-K$9m^y3(&nAZL3%i9D-de3GOrVm zXUGC-&GB`Qc2H436<@0*g!prG1q^d+sq93!6+(9%-WY_LVBOFrfXa|y`TgT8BLL|@ zzlFOHk>Mu4RpVL&1e1A~R&gjxR#R}W;74)BYbi7ZYKblcE)S{!d!C^3_V^i6Hd+)` z)FatZZA*^pO;K7qA-S+T36PBl+sxet9={pA9$p)iK$H9}LAX_Kw1O>3+>={Y^$q3> z(y6F+N5y}o^t)ox@5DaQkDok#>17bvD6iB!NlcMRAeZe(D?B6;)F9^lWC8*7HosNt zsSaa@JGA+T&YQxdzMBHDH#0hvPbQ5=I$50ZRCgLrs@)`2En^0R_Be;t=d}{X&}`&|y(25ye@d}cSLxMCkbo@w!)w4S+*we%S1Xd}aT8HqDS`dz=twb5XiYC$57 z^X(cv`rCHfEIZDs6BrXGFt3K&e=I?*mhaFi!bgKfhk$#?faECUkV{_Cf+UP3vnOOS z5|`aL82Wir)9SbhTEb<)$%N?+|74YzJCFmY6A%wI=^Zwh2T~?2C8cDtUuUwif7 z#awkZ8ji+zo9fOyw|^&V(Lbp)X?E6BgKhkUDiJAc3JzzTpI8@2k~9kn=L_Hu4EJSx zHB@5hUoR>0H&Y}F=7ah&R8|3@^flrm#zd&75{zT#zTsHY&~x?JIdR{4c=PF=J$d8J z!aZi^Nt{kmp{c6KFgIdW*~9;4e}#oQrTwFTxRs5=Ul1jRNZ`lnPfacX3|x*ZurDEu zyh{dObPn_mnvVqSv4!$LyJ^Lm30Jf{WQe_}oLZwr6qBCrKGcT5X4A^@m=UtQ{9U#M zc>cw1DdaXQ&yU@Ss9&y@Ay#Emdrs%rLeN?GKUSmGDV*pru~&H2*i(x>NBj2|OC#f&7f!o&%xZwzx$A0ch}gaElDVRdR~ao~IY z{zK_u+@qrT($&G}XY%fHXif2_hP{Ma^b>ujp`W?w;ss*!JCyRjc(QIi~O@P8lraC2IdJe(k2%~66-Hz z6GkDE5+?G(v*H9Lnr)_Ot!5Zo&w`lq-!|zhpWjy6a4Q#_c+*D{D!f|N_qRtXDQXoQ z+E7ueArlH-)4FIM3O@i|5S>AMz{GayBkJwKXbSad(xmLT#K*R>A_`4Kvqbu=#RM>p z$*JcxE(#x&Ed}##K&FP){#NiR1FHK`7Lf$9Yj6;OvJc2Fu(Ce}C9sf4KLWvUiNkOpwRos$obS4J9d@6_ z{j2AqCvq1$>vZjZU{X{vlZ8-pG_Xg=6fv2H3-MnQg7-hjhLv41976xIV;c@IgnaTR zkGXw_U~JnZ83wT4j7edr9-*VG5<5StQS}xAm|r575R#3z^+9SrtxGr|ByOExEPF!W#`@8?WM5(a>!(hbQkT5xIO}j z06gco0B#k!f1O$NXHu$8hhe-&gW|n;DNf%pM5^7{}XdC@!o}PM6U2Dj0Qa-wrqcmU@sAS-{mEU+?{q%bCZrhdk*uTd3As(dFs@N-9WobSaP=-}Ri*)CczHTt^4`QnQIk>Y6(e{WjosVjjifD-}E$jc^*F@s zkm4Z3{}m-BqmAPN_s<*0vGEry#&D}rhs zP4`wEeXga&iQ|0H2dr{QAzmejt%_yqwzL8e(XE>V2M=yVB@g2%f$nU zU--lohcrna)z|bq+mys{%34{$=N85&>E3!HDGd3p(ru)*RM5x#*xEv+wmj^4ln*&v*d$uLW`s4x!=NlYIWz@kWk_Hi;TFd zAF-$}R7pi4VZ27%5oDaEEH%${TRWSwv}EFY;cnq9Xp+!;Flu~@2J-T@piM}o7yDN+ zSBI#Pm69B(ZfK!Afpt)+4Az_{WFd0Rj*=<2M^>*L^b>vgC|r;gJ-H}b_T}d2dZwI3EXyYpG~TFJRq3zcQ%gI>wzcDIn>yR@?g`o{#BKS) zB$ibO2Cyak!9ER0aOBkCaFpJSsC;kGvfx2wQ=6LYf>=~UylON0b{hJQ?qH+{TIoC1 zk8qo4wS+QOw5X|yl={`J)YNwkYO_YB88gYz8>ZBSn8^(-7nLAyrR=D^N=-n>T}}QA zj;w1Nqf+Xa{ZdUpwvuO#I~>;080u>@>4*FK5#&OLGrSr=a&j86s-GLv9ax+l%v=|g zSt@`waGw&NK7u%DZ%_6sF1;2&lrB)oAj8y(VG$3MRVMJIJ^zRTej|e2oOk05fcu+Y zBTdK$6aJ58UL7_$Zt3W)MBbxuo)$nCb4%>Cu26!j9sd@D-ii{x65HH813bR&u3%J) zPB;@ozytru3cnmeogBpD)}I_w8Q@+ZFbDtm8-pkXEu^HtGtEB7>^>;u188%%J21VJ z`&&r!%t8iPAKL;OL&TOoV=85l+47w=6K7*@Y+`17+OY#ysHZfquI%+LVWHt3 z($+Y+7Sm_3;5$6K6Vru_m8Fnn?%Bvw%udc!%~kGZ+dDsW=hop*Dr@S~4hqR}`8KG( z;8H&LiJ2!~$ldza^Ai>vu3ewc7dB3< z)Y?z!fX#Z~pdT|V6w^`^vVVF^8jhH%Kl|XspL^syfd&-h4TW)&abK;5WFs+Ru9(YY zekI4e_H7hwOc=SQkkSpf=x02u3o{6trC5NYvh;J4#lc|wBL`%C>Ad7~^QHrM?Uw`m z^*Mi33tO@u{1SS>?K>LZ4~3V~%L)g3ES1HA0xQVdyhJbETZ$x}V0MTp?q)m5hM`JN zQ)u!8^8(h1KqU>K;OB6hQV#nx%dD8}I1|-+#@Bw5m2cjjbJLjt5zpM-cpnjNI#QaU zAKrFWGB*w!?FdI4oVQs(fJps=EJ$M;BS$9(V|{CwU&+?M0)~|XpC11|0yj5444tyO zoiRS0sI85Yu(6||gSnlPt;4Tcz|qjy#tEN;p5=ESq;Dr~Y;J1i^t&Sr-GA)2 zNlDAgi%|(UnCn}~DF04LIO$uN8w%K%S{eU$9VI7YYt{cs|M4qoZe`4f&qn{NP{fDf z<;DNMaQ>_MUpREXR!+tazwubKEt|V=2W9npv&%n;Y%=~{NhTkLRU}wkw zkE8#c9!T+UEfokiR9t$4^s!$nP^R$Jw6O z>OY>>81R1Li~NMPM*6M4Bo$W_d8UYBB1uY~o^eyjUcloMz(sjR(-fT(E|$=j9#E?- zvX2R>0~hTGfJ<1NSejf;+j}mc^?4=C;$nqtCGoJ-pLO>dW;OKO21m zGg)#;wHC+JGnu);lx;Ve3ddC7*xk^?cAs`qTw&}!2hCSuN)llpRVF@kAie&O7m9X# zuP8f>&Iem)tNv`|K(_m_Zn-s$OPcI{pk7hvzqpi&der7ReQGJ6P$1IiBTI@I3w}1M zV=vYN_KTQ)AZ%f-h-O+tf|N12H46x$Y(If9Ar#dGJ4@D)y(*2UZS)xPTZQPO7FBi2 zs_NAc;CsUhRzmn##FB$$xb@WK6>-Bz=fAOyO(ny;Mh;1s%U&2vbpkPJM#-9d_Mo!d z!yM#?`|LOf6qnu5)5uawjFH_|_0kvQmd<@{ZuNj*xtoV`1h|ifE5V*_2(8e0#(gk2z%v*cu%v zk&Kc6E&3ZCQ5e_QY*?+bn>2@vSb%X7{sFxs7faXE$Ef< zGs;mdrJ9dgqySxa&30@3GgUj9k>57qBH2HjSBH{u_>p9pvWGzy$O8(}oE#R+JVML? ztBY35z^;lwV;mA_=ZxRcw(>NAq*>>6*hPR62~5IDhcxOHm>IH>)rNeHqNL*}8d9WTCQZ?2$(;rOX0`{JgJ(NqxUOluBw5Lzozm%pqk;+oKL0oBUgX9d?95 z(TnL$F;B25ID;InDLumb4T%5!Q6MdeTr!9@gU^l3Ez%YpOKGT$)N)pYpp+;sBd{pQsAerUS*nWu7h}G&Hej9HQrsfC!FLtA#&qfa z?DgUH@$mfhJUbB4&c)Zq`w95M<0MO)K-&&iDJ+LVCL4ydIg6w~=?LOlu_`b*tUBDOJ=bSwB*OyoafiL2lF*QVipd<{}wQFsiJVzBhkGD_7In0u)Kj&l}yNO?` zk)tjZ|J`8<&e%1XFm{j1J>}AZ>APltBBUnbiZQlxw{Bu?({3Vqm8kTe*Ci5dj%@3I zsvTZzo;Ej{r~>Dgrbe8>A6EricZA5hqE|$X3d6b znlE)_@?N(vO#DUJni@K1((>khM`j(HI&Gv<1}qs$Y|}%mEbqisBF81?YQHWo;A2CI z63s|@Imb#RWmpM0e1+_TGgX>@$%(yC?iEo7=`FdoF9JEhfkw1a2JMa^j=E9D5cU3N zA~{GATx9__ujn}jWOI60B$x^{A_#Ig{5Vj^dR0%H%bG`NCe;F%vw<3w89dj0u5P$o zW)iy?uXFLXGZ>gPM`5HiqmoEI_8Q0$9bmJm^Rh*My=I%hIL79-{dK+l1)-Z%|N0(W z`vj3)dPoo0-qNVO0gIti#^#yo1(mfr6vbZfM0#0vE`<;5HJ2C=!|G>h2ae_>q_cP| z=1uuy^y1F->hAD%d-AL^b&I{&X#Z1GO6cUiuPhpx5e-nfS-jhWy*fBBFkEl8evrRV zou?@z#6j4j8MtJXkq{7f#^4z4NLRM1AT~UmYua7Et?P5l&0AemPkP9UDMt%kd<0`* zQg^)nF*n(spXw@=n12U=7MEJm4zaX;P%2X5bvI*10*(XYOg@ifo|Iyts2a{N9>lO}m5!(=ph_NPKFN5MPwyd8 zhe^G1p%nY7#w=>6Xdh9yNd6S%n7N>Y95qiFd|;BvAm@wq(M!T*n|)N%?c3V@*l9rZ zxVvyuyELu#u=R4o8Q3c#av5kXVjx@37b;Y%2Oo-Zjx9q?;gH!BBy`>{8KAONUOQz6 zLNcu6)ELaLdi!3A{4hWCA%i^ScpV)(%dM9!)Ft&2>wqQesOMQYmbjJQ1M>;;upKkG zc!0YpAypk~;|#X?UY6pDA$IsBz1H0gkERIcFbH`~Ak`lgHQG)f-7S0~y$QOqNcO6< z4ECMCTQwqwP@k+mL8hqRGDi6<_5w8#_*{~LZhiWVwF^sMqvI~W-%eFeBD%vL2lG7M zt$OgK>&8SfEG-M$62=obo8&kJUhP?2JY$X=vKP7hHh4=ATmOXobTM+vmE8}lvz-<$ z(M4~0zva5jN!q*<`QxDb)UTkT_SyAv?b(T+6zo(UCx8e9DTp7pM-|)vAI1-fdEcyV z4uRJ!UZhx_;-Z`afu}FQxr|B*v_Kr3K+_QJ;e6eGlH;jswtm>qrZdBWVhx6=9fzn=pmFj8(WryNkc=2ORjtVNr#n{BR1*N(+YeOiT`V5*UK4{!L-LH66Qt;Sz3BDQjSjM2;^h!GKwv# zZo&O0^~eEuD7R42pf{wvLMwzXW@d`QUEHbuua2mOP8D}c%XCc5q&Sq((E3y3``T&> z$&t-&(^~0E@yJ8P^sL@U@Wj=TyoZ?UC^&09f3%3T>$ zYbio-k*b`Tx};(FJxkSn(simz`PD0S_=E-lilWX=N&MoQcDCrnhLadt9OtJ!?>G%4 znOFq3k8!$}^&Zt3l{Xay8^4wqqJuZ)iZZ-!enJzRO9DAf*>K8?IM<0k8q9&|&fSR!{S zkx#=jfySZhVK1;L*$z1N0Ea-gNX+W?CX9Q9M^8XJoyK;UckH^1GSv6MGF`YW1UqyG zo{7qNI;mu^H;Y?sP*CbqGW{%Xi*8qRQ?ry+i(dccB>kzQKAS0fICi)(u}tJ!LcQ2! z2^EdfEk6%>6@zb{Dlk+kod|oEd>_E~=uoZjd$U!2|4_iQKH;xF(@VYLvw@}hU&S*W z{<7<1maz$p6P<-1n%G=^qu^3ms2QFKO_)U*@g)pcD_+80>k=)EG3{#<^H-q zps4(D)^-F3(tyr%`dJEoAW?uNKwJF4@_>f`vw%npZ2CGvBUA<ZUMahd!L9B|6c=4@H_}Wr76RqlXUz3{aXHoAqzf_ET-t2b}>2I-a>J;|$4qSv>PX zuJthY(1a~o$Btl`Z`{~(k>!wHzf~#Y43p38Q$Blt6M6g7<+8Q7)2c zJA1@$ML8oFCaaytD4d&=y})iR@fJAmaA{ac=areDIIF;{4?N(i?+;*Ny1RY>8@M&b zuN_S?CSc2J(7rD7|8CD(MN)ZXoy<$tta=R-TxP76@lua2R-vi~%MDG4SH4Q$XMw&7 z)}pe0=Pg~5d zQ#np5(=ef0?7nBHx~gvxZVC2JOEZ{8t!8HLefVQQUAXQnbR~vPI5y%wcgGZbFy1Z%wO?Hn#~dHF<z??Bd`!&l}HF zy2sl<>?d8#I#&f=A`vt6rArkI*o`B0_NsiOL!ElL%52ODa1qe{cHZM`Wbh=Z#x~e9wNvP zGtvbjW#3fGTajmyFZ~I3h(>wjsYZY}rav;@>eCO_ol_jA;Rn2aO2Mz3ZMP|s3rUy!Ix?l0n4{h3 zhPL&5bw@qUBsm_;1u(dS2x-nH>=CQ;b>;WP8hIQ`GYxS|VTCc8<)5RKPkGD_l)uN^ z`T~gUg3yxOXEt$W^P>IWg{te_@UNBl`A!U=4C%?!F0$W6vIRT3DP=#SL%%V zYskD1Tf|%M8-rUf=r%h2a^BtGstcCzWP19Sag$wqXfUxUkpMN1XE*ul#Efjv1HqY2 zhc5B}7+=s86RcQ<*l>zS)AeBH&*NR4bJL~LwD=gBT?(KL)dyTLW(aqu-?ron6XFw7 ze6K%o?~FmOfvoz?b!;cy_Lsjmfjw^6ZVkJf`mW%uU@FpG^}R@M8lBxf4}l}?*>h97 z3u#SuG?drMrrXpH+3sZ*v=b2BSMA9@^&kgfpZh-IHUZRa%;mtxp-u(yxd`o>5#}w^ zVLsul<=o!$b><&v5qEZ{oj-gsPESHfcmX|={?(Dn6-qY~3UgnIPfwM1klEjAzCunQ z2+l`E|9&ix>L89@{72=#nO>pWP_K4Gdb4*MWxa1O$6^6yg|7WS0pLa7Anf3|LBs(? z^L_w9d&O!#V83b~qI>ylQtnLD;kZTvfUi+JFN8@MCMZu< zKTs6>6l<=b^0Ys9i8z-)p~=jUxw?KP2QxY&r~{B+wPx{e+1kRL`3V9t+^XvH!I z%S{il$-)>RpX6a4T@W~f&g`)(KW274&dk*rb$r^2gt6U0GdOR` z*dT+kcHW$RTQLGnr<<;?W-NY`m5G)S(FVfij;2?Hm(s9<2v#gim>Mit04PmwN))k+ zSq&Z(LI#4A4}?U%CRX&A#INK&BTt-Kyar^iU+q0|%!I+pmvI9PBi2$EJATnej9(XP z?=!?ZfcHWD42{4F4Go;w2cri_->9C2xBuzq&5wQQtq2q3Z=;8v_6HRJ$`eo3=;jV* ztZowyII0_rs)4JmnyU_$J4DeXb4%3RS9Zw;IvPv1j`Ko1S-rH3`J!!;Ap48L**CbT zu{U}`;LM>YWQ!QHkA79g$tQ7)pK1>H5!l47b$5%9(hj!`+6+L)R!@ZAgsE?%k46!g zoS#b1_@;zDYR0ArC|Yr7`g?4fP$X^9b@c|uC$ro97H{hk!q#^E62946PQ}SH!+8AWEPjUipxFh314|mR8~PTxlBOR zQXnZuQtlRAx>EKIuJBgokzGPkt}Z>dsQ@iM&#y?WfK;hnfJuW)rc}eVv{8;I=M-96 zDa$Cb@T*8xuFk8FwnWK(Q=F}0AUBya3;L<)lVc0QE}IXIN)|P63M7 z%0WnV<4BEF4Q9Gh$rKDF%3Ncn%^F#um*M>*{TfhGA5}6x&dh1o7xH^;A^!p__+gwo zAoCji1+!v-2kr1b@dxR%N@@h4cVO4tzYx`5S}V|WiZjKg@@v zv%V|ou1aaUQ{>l@tyC&?H`G1)dZ^?!h+JLeU=^OY70H^tmp}JOFZ!3N+6!)Fx zCiBYOeuC|_j}M$ z<-M{h(@gRmim*0Df{mxN_+qI8CEgM+JAl+ki1T_4znj%iTn^u!f&}M;ne?mgA2rS+ zdU%htfh!`-Fo89klX&L5?qZ{wV#2ATG^D4C)Dy-Mr_Xenav)*=Ml0lS%`JN1d$(vP zm!)%uuDW@J(=O4=qw-@53p}zUPPrVKqtEC> zQzQt*OI}o3*iOtWtX>T7fV1)S-NM3GhF3ssi9`Pt2nNW(X*3B z8){D38+*y7SSXmshgBC`G|YlcCVVt?KRH^z*vH4&L@YUci*ms3k<&@(gb zf>x&Glh~(MLvQ}rUr6t_fy@@wBvCg+P8IW1&x@`J8HYHE` ze40Bp3wHoH9u#-V0i{=&J7wO17^{j`x9nP{fN#P~Lw~ru8%^kq8-^Yplt@~^yQH|t zL7{@Ul_w0DG*q8AH$P@6nXk3{#%f~a`^CV->F~_9UD5hfW*2?kE-p=SyY}HfJj6(C z{lqW}hX#0}Ys3dgKE09X>={oD5A<GaH!B$`BmnDmfa-X2AsJ151pO9LpOYs5_m44Rt zcN_P$QePp;w>f(|La_6-K`y+45n2MyZM*y<#%CUPWM;A`y4q6aHxZaDEiBa>Qr%@Z zq`KYRMOb;hhEYNXyO3tc)b8)0Pne2_Y(h_n31i{y#}RGZqm&I9w;7-zW-`jSHE8}rs(RFo|R%Q-Z)qzyVHgtdsNzri^`j-^BU_KjXci; zCIvig`|}3^NqCBPOaqS%pHHyq(sWz2;A_!#Oj@T}FI}-GaZ@szD0qL?F|kNk=SQqg zNK6y-ASm9#CWQO1a$b6zLuOso>~N38?RYgwuQ&xe#z1}K@fGkpmTMu}w`v6A)4z@; zfk6s9Wz4#jKG}9ufRTrtM|V6se~S+~Jv(2f?Wv(o0ds&9c)Nl^SPV;8EbPw31j*PI z$I1Y?Kozi1L?8f3%Kln@qEF{7k;e>$;gh9RKrDrn|0`jiNn0$rDl@d6U8N|_rWE_J zeUmp`pV_?b*=YTE?%w%%`S|*wOG}x^L{)ukt+LkrQgr{>ySQ-4wymzQvEEYtk_>t@ zMD;yUK3jXeRl9Thd}#63ewFvSX@$FU(E8r3_5hz?19&Iu+la_;ik=rCX$`0*;2QT~ z@{AZpHQEO^+^gfa%Uw$AOs)afhuH>!fBJ(N%`gV@`UO-P`K)DQmCu2_%$`l86;O?Z zw*N8*4n`?dX9W(;ENZ5D2xCYhof<=!pTsQDuU`QTWX#!E>S=(df;ypZ){dhD;o{F^RN36P^Gxrfu@iH(#40|aRPQtytfX?CGjVpoLVt=|FS4KDJNS{u@tw*z49{>}K zM@WX-D!~pP2W=x-1^NJ#fd{B@LUk(}fPsGtxI0GAL6*hO~BYV-+QPo}b zsF(7779(}%yIK5w0j52!#rEnSHto@K;H=+n$Nx(zgm2@R!oDk|J^&aX=pVYxS{k_( z2LOCxsEXA8D=I7uuby+}Pg9ApAQx#PLJbw0$4iApBGt)0Q$a>@q9KqL;;C6!mx|=h z!$Om~la(;awgJ%$lX*HJB20>@zx#9L_^7ZzA!45hc%mzWFvtZe*f-zVppP3@1qzi+ zAIyMlGX`1TC*QdR>xapqj{WW3Ndz5Yr`;+8#Z;~|0G*knEbgogWH-pvAvI^Mum8|h zmj^Z|XaP{8G$6`KzRrt#|{0W*=;4%gL(b`!owmRU24*E}J&{?Lx2#b%Bj*eE$$ zwRQ09GVzjj{4C*;kY3eQQgx|XiUu*Bxbu3%#yOq>2K ziczpRE=88+8jx4=jLOO%Yjs?5$sIoGLiYlpL0xuoF&azbrFlolC#1oA1 z1QagwR^)7QEs9zy*vmX3+ln`mw$Z6i9%i{KLVPFD2@s}2L~nTadREx`3ZC><1YC$% z!-Q9lo@(e*NJtTiLmsd8S=ud0Ve z5|4x4rE-JsXn|~QZ3p7Qwik-EVd}5H?`XiSf6|FU^p*%ilpzGj@diY#^h366YU|4s{5E_Qiw$g5d!%b<8>9dG3fsw}n@; z+14*XJng&O)Fx5Mic!wh@#MXoiTrCgGmbzl+Eiv@0W9Yw?qk+yxJ^tiQ$eFyMI@PY z;!rkTVZkrKA?maudnVs@wyCH+M*?M<+u_Zh;L(Zb_-*LL#>b`;0W18QiYsd9WQ|~G zzo;d4W+u+vP=TnDva3f==gK@Ddqn)lHLIqy?3J0${%wQmTBpmYcV7%<;~1v$LT;UDy`HHKUq#*c9`kL!nTj$aO+Hcg*`is>u&b^FWa=ytbjjbe3xkhq@uKCh!#?XU8KKBL%8D38)){D9##1IJXrqt)h6(UpTzl zS$U1r*MI=rEMZRijIX7ldY7`@c3J_)=Ty6TCD!^CQrB1ru(bGA}x`rDbIZma?t+e~b@HYr<=@7>R-FGiiJpTM4byv90=&aznc zL=|nP|8Z4OjiAh;C?!LW6QwJ!D3eOy)3sNTgRW|^B1gp)qWhrZCvhh1h5pDBMcsu- zAK5GlUN!C2QGWDNLa|mit27TDm3} zf~({;PztJEa@ZlhL+Pi3v3&Y{rnvzdMMK#EwPaSp zU5O#K`Bc_O@b5}Y`_sW4k6z}w3ktpx&>#)lnkblM+SFbqU3qz`eZE1=fL%R>%yox;Iy4av zbTF{Zzi%yuHv4-wTPkVpXeR2!j`q-73=DOkwU+$EpmC$(v3Wld@o6U7nDWSc7UaCD(sn{=MK%=)Y!z4bkiInjENSY`Iq;lTc5Y#*YXbcMvd zWqvO;VLP5Nd>EX4Q~hB5Cv$xK$@)oZ-uPo-Lcj;9?n6Z^Q0LWEN_>X6SC>$9B=UD+ zG6J2Mj<8&HlM8SdN3TI%Kz4I44Qt=h&Bo|inyr;AgDiXs_R6oWURyWdA`>lu56KN- zCcgOZ-tV`x?JuJ=sc;AcE6%D{?$&?N+0E+RHTSth&c+=qmg^Ia+i9v(C3NNH)95(h zfy(!dPLPtf_X*eMy-@D1uyYm{r{${Dwun#H72kVrDNvBiCipcM_Vgj(W?TA*9mEZL z7Js~jP-kc_QDgwQ&VCJF8NLNn-_aYMl?_xMsU3?|ux1NTTI8+GREdRIZjaGaYd;|i z3mPQ6$};45zAOvp7OVkCd8Uv<;gTsI;{KBy*31Rj9|u}!CM8c3JJKMUZL6X=vO zLUsB7F?LTunuJ}0uFJOVsxI5My7-oD+eVjd+qP}H%eHM}_qXTYu_NY-iI|f-$df$F z$jE1{>o(p6FJS0E|8ZM+BxIx0;PqJRK-81E85wu^_jb>Hd?=-8E&UnuY#2oJ;qkc~ zi*fcmK~275Lx0h8zxaG=fC|_WL~DS!4U7?xQJEWvm#T@OUlt!@TL)cN?nuZfngCp} z@>TyuX%Y8K{*vw(OQ+aFo`()E6Lu==F=ulT1+_nAP2gu*ho1G$OBE$_{Se9S@yGh% zWMjuvrKZN2T-w~MC(=-nJ;EtWIAokgJj$DBFB}t0X(%BUCzCD8GJ_H|6&pD4qHttU@c2s6xnX&@%3*ryzgFh;`RW{C25;DgA9-!0!R$g2B$e&oN zL}!|Ap+YsdSc9Mvhn#u1Fw*4(MWv(~BS0eLn1b8^^Ozjl-9is&N)Uj7u;3%5dnzwY zER>H)p5) zLbm@&cCDWf4>D$`GK?R`4lRa38!fhKEw-g;r*qPxN1&yk-A{l_9zGxHO3Y}h|k12GuJX2+XWyK=!bRS1&BcZdmJ-ufX-CD9qoJ_NE5<$tXjNrG&LCHAn-yl#># zdl_2V1HxP-@E?TO4#nT$8W25JegM!Q-8l-3AIt-citoGvD@NRnx>8f5#d7kGS-C|t z&pk%8kM_6?c+bk22q{phlFGajPWY8JB-#JMPe5#oyHPg8y300ZAwxk92*sqZAW(4N zbis3ill*Z~S;&`RlZACip1N;-533DrB1WuP9mLy?rU7K+TgpwS=NolHvRfG9Z^zlj zVNjp?jcynkRA#b%j~Fzn(-c-^Ho2@DWdww4Ddg@8+;b$1)HTrJdE+L zNWhom=t;~O@wC;^ebN8I@cb~%c79xjI=iF;wxER30M-W#7kBz}j2X+Ry0T%y$nFUW zWKkwLs*s4Pw29(tg!Fagz_b(DxH?~+KE2a+i`gxu&!|X%K_`L#GXZpPB!~58u`=u% zpfW|BguxIbn}d)r=zF{iia?ks+OP4*FxUN_{hZZc?NL|Iw^}QgM%R0r*O#PI$bV~U zV2lX7k%HV&tYR5WnZW@YSuuixw!E!*;|vxF_WAz_f?E*8F-L((#5PCC13Lg=$&WUJ zvN1g+WBDrj_qPy%xY#x=L~7FiXuCB9n>kzB^JZ(yXWhr^#^)r<3z~75z&~aT2&(Nu zr;~{kI?TyNUwqy+DJHX63U?Qp;uIJ$t@wa~AD3Bn5LeJysKBs={4&87lR5J%XK&cI!3r3@UtVd=Vbg%w_EWF>I9)I|O8-Lc z&lc1rPyP}ku#u1Hd?{fQC^lS#zJQ?|vum5f^xm;wiCxi4zKxpR?`itA?CVknC%{MF zI?dVNzpa$c_FfnC>A^4Dz-u5AaNE>~_{;$bi6VetJE?2wk9F-hUJ9`E?&-_o{`y|s zxF)bDH-amtaS9%RBh(-WmK>P1*V^m>`ZIx1e(S9PVqciyzrNq!I<%!@37t2LwOd7r09GcYVPz zQ6dCPL3&Vq5+rx8_HhTCFf>T=Z%)?|MrhMDc>Zx%B~c5Q8J0zx0$|9q3XcR5vL>)- z7H=uwG=;Ir;AcvaOhVM%yu=2P#eZ}0c+7#(h4?TzL@$UwZBJ^19LEeBbMtK=-dQt zFbn03o*XUPO-P%^4Z}qz%Zu!|RqQgel`^$ZbC7KcGHj~3BJV#M+r3p06Ah?w%6C!o zGbC;PCiJo72gkF`$hAajomr}RWoxZfe>x2u-;RtCSoSvNZq4=*JqEjpAv8+7k~Rno zCIt)W+@EKN#1dx{8DDhNvXa^8!9)XAVU)jPO78n?=+^=&^0WRtbD+zT)3n7HDGRu zwa(XtA&I0Nx?ce^7cJ>hsO;uioJ&hHO}S;SyfTT3j&6cYZHo4i*Q1khV-geE~>7b14q zsWTJBnPoy5QX(K&Q+_f036R~9rcOqmf>Ay|^Q`91jM~WzY?0HJm4_+=uQSLx273xF z6WJA@+wVM{c`7@_o?dD~t4J2t#%nRk(}?3&r(~a&AXU3pN=pP*#m;kT_iK<-J>~>k zt%YpdR!rrnzrGyPTo`^gK3bPU?j&N=7i~-vv}EyB?5X4k*h-(g~C(uCj`(dsL7a@?cO9p4b^ebLQWI zK&f5?vqaqXzIZr*j8X?Q=fSdLY?YJ6mX%FUFa*>NU{KJmT+YA#&p3o?$UFG@g*Qh* z`NXFs2(s$2ZbUThap)vt5xG(t)RfB()yRJm!Aq8jMru^p%#xrX&FC2+Z2HKiO8Lr( zs3+NrMKxN$L|n1Qp!qDDi61pRH=YDSn=5FG{w<`p6YK3&zbstT6#3ydQ`J1ezuym@ z7c%TXEBWCp&Hua}_jNAv2!@si{(0_z`~}VW?9nmUAm9_42L+Gj$|hvVx>qmb2h(Yx z-X?~|7L$agbR@*J;>f*q_xX?}W){8G@=7a@@+L~|Ih%H=o*;18p8ga6snOFt z68(wwOEd~K!MGqe9Q&xPA~UjDn_Mkgo?4QOZd~dqB|R~xo?}#Poo8Pwt$PaonBPl) zUX_B=7&&49x|sD8kUFwFI+j)&R(XuzQ0rub_r>j&@{v)<`AMdMR0aDlK@MqldcW}OEpr?2@vz&*~I zDX2{7G=N|(@~M%#I+aY8>KKtcB5@_*5LYTm`4-ji^+#HCng*uVtlNUzsd`Cu-qI3| z#w;Pv-_C-r90wCa0Y7F)C~vq|Hd?;{wEKA&6RR`iV2QMFkc5KEN%MuXg+f+)_|=5^ zmv%Jr7IKsvg{w-&&b=sFVJh7_nMFXlR*H@-d6AMTE+q9Zd>mwASvigGw#T#O)=2u1 zPHvU3N%Kd`%W;;{%2$csPP#{c$av?uQV&N{PqVYl=y~obS0~2ItHn-Mwv#qqWiYA6 z1xzWMTjdrcPLxR_g@D(K&`uNeqehSXm>q4#+A_1-`U~*V@xQMYaiURHQCt@Uh@R57MDZ#M}clC)tAz`M6`UP=v{>`pAzLvlrtykC-MGq!gYq%#&%jju^b1<=S^hA9oiZdx8O}c}}vd!e(JD0nD?)=(o-t#DDcs_eR zJUaiKbGiLH?y|QJwI|wKf^zdWG1o5Cr;aEXc?G5l2lNWVM5GL*q2LdTCNj?yHM3+# zEa7Z4B~vDbvsSN+yoM$q|EkZnq;rjkUJ^==GQoMw>wV!1lQV1EaC5s!@ygwK;QbdI zIuW=60apX<2%KYKO$zRQ7E0gKMpheOn;lL)FYY%>Ke`9_XxQ^L#@Hn+pGWr_pE`X< z+<5Mm+?4pvcA>VVyO6RXGYjXNix(@VD<=L$Ifn^nN#k9CD-57=Sz=VFvHaTTH#AwTjjZ9TD37M5%+oW8>&Y zp1A?=S&*GflcibNY*x!al^OJ)IR5ec3Jf?HU63Q?du$47oj{g%Q3)x zg*d}54&R#cleYxm%~6MXo-OMeFpyVP5qU7&ekT(yNU*dS+KJ_Ha*lRV8p+koXc4O8 zcyDiH-FesPn7_m_7p6qOT{@&6qZIx%XHq9UJp**Ah^w?u<?6L;hB=GPG*&hBZ;dI!&ywBny;kP4Pe!o zVvEj1e8s4J zM|t8AT)MeOSi9U>VdU`Vb&JK(2weV{U!$%rk7gMkb<%MH#%%OoxG$?>;D~DymLtN- zX&HlkgxgRJ*7j&~x?3$TJ!JPM&ZF1ObM6;_5HM&?;gXM#Bnk@U3D>xQ@X((pQImn; zJP{&55I%`KiNjcLxo%pxX5ctSVOwfq;AzpAmHl4F09Vh$ z5^AqU@z>BqREOkv$I=nshr`j62o@pd;+_41A47BRD29$)&ehNB=jd*KHdK9UU%fMJ zwh+YaUpoqQ6ex4EDEne-^o^7K(_#x#A_H#L(vn7A@f;$C^N7nRN!Kn~CgQ!KAo4Li z3nKDtASz@n#j!-P^hZ0#AJBk!Wh)2 zR^cuO4F}_QXmND)IniR#uN}E|JfI~|QVpU{*mM3+PumAGYZJrdor&f*C@_9fHDjzf zrqylX)Td!oZk*RAV3^g*Y}x@a$F^1Tjo8>aen@S6{1}$8E&UByHs{V!-L926S$YgU zWt`Fox@!z2yxT%zm2w>`n1ZqFp=e{Nmw1-D?>TkZ7w{+5KW50BDoy%eg}2BS*m3Q? z8$(gKrd$7fTy|^!B+RX{)KG3fS>?@^|XFZ88e3o2b`aJ+&uWgs}@&v{Wf)+r}xJs5rSOF18G8?N_&C zdzhZ*ZeH84u4?Rw{YvQTT&|mZJG#d?iL^%DA?rO&nkM>XxjW*S1GQB20ID;WBZUE` z(UI4k)OS7^NoE>>6<&cAqN>H47S1yMWH=vXa5W>+^hI(WGA89=F}J>YyMz?bkAQ9# z=L&ZuX@uC_X3%7CA9O57L@p)ZbfLCB&+ME22=Ws!v=^ch<~>xJ0=hpYPe;IKd-o92 zeK*c#ec9INXYc(wRX)>QDtB|nJN#FP{b-44d7qLH?akRob9Apkp8rtP$VdrybWmQ9q(#w`^wX zXzgmNoH;$6K7MQV?sDNdVzwsouJ9avE4n&%RA9NNH=$Ctvyk{T5$K&QO4JN~9aN8t-{|_%wZT`XY&uVSUDrF7JXYSfs`_OqGpn>GvTt6~nMk0rXrW|E!Nk#@Me84y#*l=Hy?j9K^OUdI50}&NRQvbO3tjmg zQZzX-`(TYR&lE_ zZEs^W*NYYj)hhLdX|0)&oz+&)yL8dtEpGPDIL{Q36Q*bq>XTVx`1*s}w}uYUZPXo1 zU8KBZ1n7to@?O4xr{AF@@1Mmz>&q1v{AT`ZeT;Zys>jFh4_Nl)lW2w)3p{MB-6j~QQvUtw}l4iyz@Y>^B@$ZV01 z)=u*!MRTdd&}a^~dNm@_FqimcNKYFETU6~{Q?lTGTMD^R^_n1eBNA+o+j1uKXmjT5 z>PZL#e{s9lUdUzpuMeN|u=eLys=5M!5IE8bo5+JX0)15w2oc2_kOO^R)n;UCvLzYN zUKk1NLotvPg=qNiM&Po!3G*;%E3CQ8s5!gR`A`J>fJg1~HHkHu*wXSL{?Tyv0-SM{ zd2^nWJ6Eg+fa?{FnY9}3Y>t!PPv2ZCuHopmU$xI$!6G6L;&<0?!uZ@ZwnaSv0G0DI z@&MPZ+wb;V!dT<>tRKHJMNHbrC6>_A%7b1bUe`z8%tFFVLWxZMIKJR%GPI*p&i0)u zC(-=-MrPs-=XLiHJkDN1bRRpOe%6sSMAq1=fdm;c$=qK4iBP=XPIOkDaA>nKZ-__nP=!8Gu@YxJi5^5AzMQHL7@K83REQ&F_)0= zr6}>pE^Cos?T+GMF*1m-?PET&adcVrjjkpvXAc5*6mb%>PyUI{QHbJ@YP`)tf(G7> z;)+|j8e(iD*Lyzs{WBtUjj+*&EOYn(c-}gx$BL1 zvTTpn*W)D>kLS2BJk|>6V zi6lE14v26Hr&nQQz2)rkR)A`oh&vy8O^Q=xnd@V~NGYqtqtlMjqiO0;?a+E;8&P!& zy<_dwS+(FD^$Fc!(B7r*_!Z@6pBpKaniEu%ppbYSq9lFk-TMmX8YI# zvEZg+7qW%+HxQ_|a>bq$b@1fuYSO2Rj;eXwLhmtpwz{TG>fsQIP2%+y#`Ik7(Up0O z*?yAag0Et)=pCCfxk#;~B|31I0L(w)UE<-8AdmtqTBKBM0Dvpa^UI5(*0F$|GNE#?ey#OmO zZI6PCh_j`vY=Wq-S{2%Y3yKH`8gU3N6h)H{ilHfrBLDYg2oo3%DQ_GW!4g>@ATX3- zw0FlGh~TCRMX&q}5e(MkuR5=R))HGYY(4=F&R<<^_YM%%ej~a{1KA5ypsTu?LR5C^ z%_i&)g72drCBr?mV*{xCVf`MUjQUxdTlCW)*;_Jibk{z5EdTD?eS8ISew{QfA*BX z;95oX%U(fb5kW!>xf#Kn{7J;zRT5|*pZO{w;_4trAZX@7LEzru4ElC=kKPd!WaH{*$A|Z;i6fr>qHxB}PGH!qZ2ZAzgPjU&4WbN%5Q(`=^G zj@Qf9QRgHg$Q%xX5b@XAUAK{=gvlp?WOV96{Q}I^Fyct>1t?r4D5c%{07|Es`h zj*^ctp{jyvVM4E?8c#>~kmVR%C%;7R0XTVydO~;iQIGrg>wH zy!Eo#;9k0kuIkm1%R}PR0R!I4cuaX(SS@lON*0LIS38cPG+$v`7!ow zU=q|1n6OzCBP{Vsu8;Y~?_jhKB)_;G`|XwYd7_&NkLe%$-@pro206*bF4oEh*ca!0 z5md%a!9yn2l)J*+?wH=@!IxC3*&o2Od&WkzFZ+G72C&}^!*?1RL%LvQ(KHwqa2ruD&F+337eRW%El5? zw@~ke1tVs@Eu ztn3m(&IH)EqB-&>~eLZ&8NTKs$pf`PLv;*g94eO#wP7 zt*Y!5TZ^B+si)}g2$dU&2jwVH8=2kHd#0oTWTW8$GuGwbV(QfG+JR4oKCy@Oz$f7O z7j47@ta~xWyO0fGm^Q)O3V7s_zFMDS1-#S+%oRn5rwq#SYNrre2HA9**^u^lzit&~ z_JTi4<~Ba5ILe=?g~cksD};T@5Goclaj($%1RDqoOV4b5s*5K8Hqmu4b;s+UHlqYD z-k-&zdk!A=d>6bt(~M4KTx-smnN!urx@XBE$2-%J$2xYhl;wDS;Z&j>i~w#TA!Y%X zS%Zi8bp~O`Y1xb*n$Axa;0^QPI-|Vwpaz`(t8>DBWB%6 zEe{UD-9P{~<{OOPpj&b;P8C48y#jDk8M}CL4(lT8Q+;hEm*1}0?W$o{8#|AAuJzRY zF7y>oK9gWl-n`kMS(ROFuE#tH-aMT^@StR?I2BaEXmdFBD9(D^@=|z?j(dqf(2XI9%6y+AQ zm228Hs~iZwqA>CrEU@udG3(bAjn6Kcq=TI3^@@}<{f=l_Ix0ZdDZWxNXcqD*JcXsYoj+Pn~Qa%M-^=e1b=mL>Y zjo|}zaz_VQ?`&$+rH(DHk|zoS6m|zOUFp)rd&0)+*Ts_5eZ7BED=Zi*&eFW02hx!v zz@3K*IMYJn>67tF3_bW&%*UMrQ8sL_m2j+MNqRt~?Cqr1?gS`tMWP~)hfJi+FIaHwar z^iZzo_xskI;he4MmnnnuujA5;t%}mAL}}~zGiDqarJ@Bj$y8&bB$*V=Dn>*pfvMEB z6e_(U>WJjpzewp4#mpWv6HToXqCM136)~py@xSAi4AFUvQ%Wv2>bNaVgNlZNi0>Q% zA>q9#TKsy`dVD-zB4Q#g*AC90%-quoy~?_^R_KZQvw6V5UExmWdUUjY*yWpTk4`R( z8a16|nTV-}<1>snvbaKyoujajw;J5qj{3eD1MvpwCCYn~m@c_=nLZfE6Ga_IexxYA zDAOMk$=)^&kO}ckQsgeVbG5=)BF#c3uTMcz{Yi1Lde(ZJf~O9T0{d? zo-@k6XlN|I;xkd#sAuC(aE;;Fa<&wAbT zw1(d|`sb4oH>8vA{SrkBi&Gy%8AHIKm4d1pXLSAph718;+zb$1cn57HvjJ|NqaI^4 zN*_9hU}{8$Lbi{iHp2e}ppChr6rr0p#Py{e-}XJZ_L{WKqjSv|Z#~)ex}I%6`H#&6 zf{W6eE?(xm8c0wRB8a0 z3te*?q|{BmeUy(blqDffDU)o~_+o1Ox_(4RRk(;+0ps2{IGnzHKFku@x-FhR(Og^l z!Fx8I@##=~EyQHkf`Da?`TitNyEyDpQPkm7Ud4PZ7fpA+4T}-P_nWVdYKJ2@^b^Gd%|3?|Gzrm8&!QR8AHUE+unz9Z% z{tNN^-)xX|O>0#F#V!>*xXn(A3i*=ZJC#GW4h&*CG9$A~XOS6>G%N*ul-sd%o}T*Q z?hZhvCb|tED7IAK@oC^@uX@?~o^pAaiH8=C>7InL60&9*5_z9+@j|wgICX)^tY0^_ zG+ALOoUfJO>>HG=Fn06wD$+lnh)D_@Gx4c`Q%Qs!mBNU2f6Ta zP9>eZ79(E@QH)+8w3I5&3b3J)%M|}j>RB~iy?&c2f3724b7@XRC%II6eHmWT6Q!0+ zbEa|^p;88~hP@LKFIG8hSq(yHa@2=cna*DiV-X+oQn4+Acsk9Df0a5kTc-WXxZLy{ z(L=rN>OLYL`eQhb-siJ#AiAkl_W zLV@A|>uZrZ312)V3Mv6}Zkw1t5x<7Eo$!l0PcQf#Ib{wX#p*D0pJhGT^Vi7FV6qsW zxgU%T?=}AAflYUuZot&Qd+%UYqk$5~B^Ep!Q^u+77*pJvr&H33w{BIwa};(VruatQ zMdgte_9byLw#Vt_Z_r(p+r7Oe`0Sfe7(qXEeoG;B}U77KXWmd8x0q+~|AZ zr4L8B&qK}?U;S5$>Jia($aa`E%og98+&s;( z9oUF#_8%!kCV=Gg`Sd!*YlY6@JeV4)HNW`7l#e_4^8D3iiQs*gyAV6p7As^2?}f*d z%5T)C&b~%#%f(b=L)z$(RqZMc5Xs;j@kk~0&Xfv9-3pHx%AFZ-h$5tJ(~t6ap99N+ zUqm;8JGJ^NsizNa5SI@i?YsmRv7xhO_w7~>g}8aMAy=^=!G^NVEVoWkHxMs=!7Y1~ zgu~p4mo6mG%mbUhgM9cAxbZ1>I2IWE+4T{vv7xL%CKP+o9l_i=AdlqHF=4~gYSS7+ zFXH@6Z5bi;Z^&BsS|Hz2_E)Jgz-K;D__ZMyff2Ptt!#Eb4`1GT7|oV^!l!+b+lR9p z$R4!fO3vukcieNQ%G(Y*SAH9zA$r{GrjXiXHflt4rLl&MPmv2*-5=N@*igO=fHJZm!mZGe(Np)3RuUaq2 z3(W20E35sA9@3ck1HbVxW&@{|+A?riv_Soxm3I}_UI5GRMnBD}b%?p&wQSLH8te4t zxrQmHml7qq#bNWKm*;2PGRK_sW9Yhf?fe(xGFkhii3d2A^luNQInYSSp~VJ3)e?Dy z*D;V|t8b7qlw?67QS29bB

@JePT{86PA;brJJxrTB}*uwk*PLGzre5xF7n^1MJn zFkBAd{kN4jK)drJLm6+PS8m<=iiYdhY14)5A^m0r{?K>K&cRmDJErW@AFJA*7dVHm z!6V%udE(2E9zODcCA@T3BPtiAYcrfHcv|8I{!lTceiP(+__{py0esYPyBD9(iA&ru zYjDer>+9cU#6dInP{uoPktmgie8k_jMjzF(O~FQgG=$lnHN>*q{#cc4o_gxJs$W<{w!?gE z$lMq*Kqe#39}=!2T3#ZW;LIMuj6pD|_l)`|3lKEw+Uon&#iIE1mg2l$R6C;H&`3~Y!Qk%mU#W$=OuCZZ@BegA%RZd^`GSZN*b0ch#Q>SGhQjW-5Iej#lz`pG~~fCBm&J6`N54tjddel(j7*eGw=hWw_l1xy~`J8 zo$nZLS$E8INdM45hZF)1*KtrouJ_#d+`O*Y(;~HLbZ5b~!-aj2=5TgP^jO8pXW}K? zSfW(8l+^ldG`63{NB?>q0(P7ugQ?csQStyA7kkjm3xfyRjcxMqXKF1Q9(>$`=c@wQ z7@saXHip;(pQ*&uutN)?UlfI(^tlrbI>S}W8TzuKw4SM-b3THL8xWVmJHHfefOUo1 zf%@Vob+P}J{s9Nt{_GBAlm(BAe18#zfNwdF!GAC0;s#a^@TH6E4gSRI>*6y5n%d~Z zY9l;i0K&Uj3S=s~my7a%d0-VbUAyWP_e=6>E#!r~R~@VFgToD+b0wS;pzxYu6sYw| z{rowKe)uaZ&GQo#F7@{0!gZ86){vPX#WlwD^FxunIj_d;YkzMZ!1qIcLN0|=Op1)B z#nt1WeY84qmvj(LszPwmHqs7i=Q+l>zY6_i6XHHnpLCGE2Kr5U{T2CI0dKp{IoRoC zwq@Y7ye8QYR=?bEG|SQwZ#~`+&i7QDH$m#@ta;jeVA0@(BKGBB`qAsxqnuy@0f2V2`Mu7OkcUJo{rIHqJBy&+cy zpBzE)1Vlr|$=YRKt#{c+%|J)Favb5cgD!So|CB{;L@}PT)sGG#ppsIsr%B2-Wu!6P z0gKo+?jfib5;&$t|2xjjggDTryB^To6zev%3)=+wp;ITNAp(!|fAYUOr2n+-zoDqg zfFBHn%?N}>QB*|U^autoz@a0OxTQi9LeaG@2qZoe3k8bA+W)Q$E%L)lc*aX8K(P=f zfZ~)r#M)1l$tuP0C~71)3ne(~Bq(1Y?cR+~aW7&<#BG9W7tEPO@-yCtr06M0X)BVT zKeMAho25Ui`Tbt~d;KcGwXH}^d)_jYRot2qsAIuWSMZ&Lhz?GY9GFV%GPTNqCWA%% zk`f_&Fho^Ysc31AQlW3o@{IG2B)V@s!85Q&tk6jkzn~4|9p;vMS95_O-mI z^URHyaCRgas|R~b)%vwS5Mi)8uH=>hZW^4`!rTs6hogxVf7EDA`n5txFF5KI#+Vnv z2lP#Yf;Zsv6<>erHnzXaV9<|%B8Xx4>Qu%42hAPxR%1{Ha*rjX6Z=$T5Ff;I$G$cc z<)(iF|MJp*1Lv}HbqYuZ zyV1(}%;iACLs~G$4CfvMxkCIfkvd=!{00`@?a?YpR8Rgw_He&rO8V|}2W$sAWh?`* za3AG~YT9IO=2*W9sk(&)o(Kzb+mzh1g?^BjsjAZ-ac!ce(Z66SN2olll62$(zvoi} zKs+8#dXT=xR)lK@=U@V3f=5Itdcs-*Uq`8`bhpF>>`Tu+rl~$-EQ@dY%e&!!|9l-| zugU;;mHAI?^Fgg&(ce4lz_%uo)K2B9BYa^g0u1I%ZMe1$`NcV2RToY~j4n~~u%tU@t; zraoY@0S@oH^il~{hMs~_B|%e`-C|Pb0~MIu5{%zMm~!VznF@|Z<=^JA9xx}qUmkp= zydh5mWYRU!TtZceh4yMyS2BBWxDIXV4AwVz!CTbsuhWJjdxLhaE(Vf2p?F>-Gm-{c zLiSRhy?r4X$~gpbM*;|?fPx>&_7bHZDXG+JlV}+!H9)PV(!1daC6{yz*?ysMoTAzZ z<#SwN_|nwB_7r^_TLyC%{-#3-e@3#+&_+7kb$fJ4)mBnJJu?*ZDglHnwni*v;vYZ0 z#D0~T^G{RmMea;F-tfDz)*12^_AYFu5DkU;st={0*d_Dy($qaVjEl#krva5^hP&h`o?QPKLE zXUxXSIJc&BH$eZ|aA;)hp5e7pQmOM<`w@*<%8vt(#DDwf(~Q)K{v6d% zi~rg``NzKrIbgI7T_aA=6`L|t-r#~9;RvS60lV<6fZPmaAIyOhp%$`OU8s&ec0hiB z<|x$QN(xIXk4^wWeesmu9#a{p@7SLp)ln&S3GWe{`lwX@vug^DBe@ZsYxm={ew}oj zGc3R{vwFG*Zre9iBk?}u9JB@Wx%EMQRc>|mD7PiM<$`^S-wq*z6xFH+jFftB8my3H z3Nv}Sb!FZ9i@B?uvcWh}Wn(i8E_!F}g$EBRxwtK8eN5{(^!~o6!crr_BD;?@Kr;<9 z9fKK!D%hu10t+Q1Sjs>XDafqi$f^i90oO8zwO5)tp~6w`8{!htQT>n7()Dar5~0h@ zP(;C&8NUaN*!3U-tw5JRniAsor_Vk7C;pq0*&rM>B^(AAQ(hcH=wKkNvymd{_4No3 z)5*(67eXiPzqQ?py59Ek3ILR{e&{T&Iq9@)@{vh^7*QZ5chB1MdaK>%Wg`pKrOPS? z*u(7v!zeCwCSSjg)zUh->=7H6R&JICW>?+AWbcpfC3z1?dtbWUL4`=J-(^E8cI*qC z4nZvsf*RhEvFWR=`Uf}K2;KQOj+U&s!-Bg~#gm?Ms*g496ZYth+sR8SPwtghq~1(V z)k-2Ku_+;hfhu}SIl{Kc!^6L zOwwY4s~+g9Gzz*R%KiunPnFNb}txBKJ%oY>$);vqyem)HX%!TS@cTVY5r` z^Oh-per41?Aimo_32U+G9XjC(U%>WpCyUfnk=_@DrG=pm)tXR+gw>| z^}763yR)NUeOg_K=mmnX*vOiaV&bx3RqtN_m&J1P^Ev9p_3Hqhe^-mr1Ryf#cRfzv z^{#^UF&yZ4V8(+Y9A!yK@7uacu#}pE|C?j-rBI}g2UOQ9oclM}Ufol;E~RLTL5e?*Zp)5v1)NqZfh~n%@!JW~9+YKHU=N!#FiiQj8C6ku)HA z8n>Lf1(PCK3KaqiwWk>Z>Oo@|5F35ms_CyZ=xMp6RW`}L=(J-&>V5jWx_Iic==5zB zs5$z`;e}wkVd5+n=6k5HTHBsUka-F>fg5X} z$3{0BAN!{^EAOGxt{rc?tFx;sua#;03GL7Ua30EHcLz)A15$P2c=Rk~D!kBq_HD;VgiF&-h=5zN1z&5_nwd!}$gOUND z(QOX42`mmK%;k`xW&_KSGKG1M?z1)O20=di; zQnZ%*v6%$?0d?MNbdCJyx<84{-!EGiFIpFn5Rt+Ce-3&d8W3t*%h591+6*FJk^~5f zL2V!NJbv`+Im7%?H8CH=au*~jJ3oKtJ~dT(Jf_+PN9KznFvP>amAIa6QJ&9rt_6XP z$2T=Z9g}D{jB8&j<7k3bm59G7ag!v-VP(T?jN~@FBBvl?3 zXq!-%bFknaO9rQq-nYq&GZTwWtM(Jaz%}!Y zi-r#F=-g!yjevb$h|!*ZZgw$^($0{dAhAIDK*Cpj*m$DqHJtHd=kUI&P&W7$y8we! zp#*2N$uwIgNwYoGzv>c{fB|zU!KPM)pe7@~!Jy?<|!+bGgyybvs=&g7A|&;jG|G_var51 zmuY=smqTuWSlVMAcfn3#;&5Qz&|lCd5Hr3A5RHSL5TafUl1#8+skSRg~bcyPI;}rI=mI94Y=Jpkmb1!Mq3SU$YzBN7ct2cH&9rvTFb&0C!CU zd`SsD8AUhXw95KV9fHmC{GAr04049M3z@apkTS|of{CND0qZjjUVau`^Zyk0-C^!r z)u9+;^Ygfd7_cd3M_r>fy{L_Pmqr@(GLlBps7s>?HUwe=F^SEKd0;==1Use#Fd;kx z$qP6McIyM8ATI`zGeMDDtizv~B&efF`( zuKdxPHm~|`x8D)F`}X_qioUa(dgTM&+YMhT{O%Xx_x$tQ7`*=RKN1JS-+sg}eg2;& zgKw4parwjLKgWL%9}O1l<}P>Y#m~PjY1DMTb{g?dPZST1C%laQ6 zH{9`H{E0U{cCRpNR(EbMv2n!uy+FeB$GM-+Ld@{cWfCk>}j@ zhmRWnZ+`Wa>F@r=eNSHW*oVzGZ(shEZ@=w}ul&eI|4?}Oqv0nX{}J&{BKiB*)tqtj{nyhN(aCHp5GjQ`~Js_-@K_Rw7>hTdw>4WZ$5VLsf+IaS@n*au6^Alw=Zv0?z;ay zS3U59%aD)V_u*5wf9}TTKKK^sgCDr-zSlqSmIE~T4peyfWzXGU*qvX(tv{K*>5?xZ zoyPZN1pdpnJ?E$2|F4feaPPMC@*lk5IfnUP-~90V{;2*J&TH7@bT%to$6lk{EIJs_}PE?@b{2Y-+u13AAkGxSKs!JIrlBmADFH?^G6Elw>#}; z{iGhg<}SZAVm|114^G{6i3NT}af7#ua=`T~BeDcDN`=7Y_;G?G=dh*F@E_mx(f9J9r{Xc$E+x#>3nlIk> zv%9Xn{U)9E%NPB%@09$(3##+`uIYU9S+_j?jM>c(+anQ zk$?WX4KI1Ow&um_&mP2TALefa8Y z{^Wgc`TkAs|Jbu`>3!l7-?djf@8HshUh{>^MyY`Bdy5Q~uhTud^5f1=JxSk>{_ahGSa{Xvp8V>^KK%NRUGk}m z{y_i0r=M}b#m`v0`;O8HIby_9xl@;)sooc!gF<(s`2gfyg+~3pvQp+SHHY?!S(a&ZnJ&U`Jt}_zd`)` z?l;wMdG=dA(Y@!1?|t}&Xa4-U%Ol@;9{b8a`38UYH9xs({-L)eKY!!x?M45IAHL_W zey@hTYcl!fS0DWR3%~a2FJ5y;{i>h6^NwqsmpuNNCtviPe|hnje&foC`KIA(-*ER; zp{s`vmo*Rn$avM;Y|oYM$vkvx?}kr*gZ=yHw_mdQ@pavoiuOY44b$)Z>++$0xbXgW zeDYNnUGt33-LW>Gz!vH_)#?Whe?AzGv((v2gy)wflnxx_Q4f%xp${Bq$}4i*fg`9+ z)m45Wca;MS+c6uIJ9Gp_n{`%M1=ZO?o$rb-vS-uccHMVv&M#!hx@r>a(hph#-4Y!S zC+SuqKlaW#b&aP&tnEA%)u-~A02-Q&ea^J6ZB1B4F{RJjI);*h=7l=M6mYpSGZY20 zJv}h8tM(`}nc8r(q}%_$_IuV?&s_IA=yjFPAMr!NG{@WIm*1QUW*B8NW!d7pn$@6B(PcGJ*qS%VG`%VY15Hm{y=Y`3(KToCDS#e|z*~4;WZnC8; z>k!0?aZTDl+G<4+$#z$fY}E8B@2+m-(Sn$V6x^jF;w(sGJX0l;VV*XIvL`aM+R~-W zvNl($dlu=TR+q+^el$zg;zeV|tOQ^f)~W`+-%lyNTvW(Z>Eg3W#A{BPi?x?`xPZ8m~QlV#U!LLTD+0%tS_oTY94Tj82K(E;V zt|i^=NVYK63#~g`&Q@de#^uri!?Q4BS&EJlrOAv?M(H9>jRWB{l?BvnU{X7yvZj@G zRLG48BrysvFeRp|R=L)shlSeuW(iiqrom`oTXyQBj1e=h6UoRRR$S_c#2kW=x+-$* zlX!SYwL?i}Koag5NoLQ>D*hES@pS6%9up;)vrH!%-J+fBtgSfQ<`LPPRY$t;LeK_6 zLAx=H`Ve@%G!*@tAgqV&wO&&WI%W%E#W@Ve+*l9A@7)gBwz zx~k`bN~jr_V1VRFlrOPZ6mcb0o!G2#*Um13#Iw%Am>CZ&#Q zS7W7TY}lF&alA~)b}@j-UWolI+!xdApWoT-o6A1jR-KawF<6n9!wy+j%mlw6(6~ zSZKvCt-qisUR>lW`hio6q&)>ywwXQfQcTRlxkfjNCR6@dn=`K<)5asW<0W*#d0Nx5 zWr(q`olE$Q+i?#M!={QxAFVY^feq{qT6p(%c%rVRl*4we6`eCT( zh6*?XB*~nznk|N@2bqVYuqmSY1ChE{H}YnEB!>rL(V8GfI?h!JNlsO<l zx*UZjnvLU73QtGZA}vH}0$`J+t|z^Ix$kVyE}JUAIa?~vWhPl}QK+OB%cZn&jfc|0 z;tA$;-L5um#c+tM_hA)@lPPOm5)`CEFO7m-$VgMZz_=O8Czd>8sf89PC)M)lNYlhQ z?$7o1st;|6?X@CNkZwKF`$Ia;ZL%dScrp{RktI6E1TC1A=()kxYMxD28(&|Nlcm5w zFs{9kbj1|!Oif{PaIhF{piD<=m#m#?&tRZu8#}vNdl&UsicR-ynZ(S5&d2$-lN=>x zVv(+%C~jw6OOia#JUwlm6MLfP)L^{KHirXoQ>;`-o*6lJ8e8jTQ^b=j8{v4!E)4yh zcsbHewc<&GZ<4o0sr4kVCdVv;K`moqj#4E-X7sopRoFq@AFM^2kr6SQ_Y&whwNR#U zj|E=9#Q+uQM)IhOk0xhHlN!O5s#Ebnjd9JHkRrKRA~JI7Z3^D+jiyc0nwY58vc))+ zd%@8xDtF5q5*Rm@;M3K)meHr$8v0bUQDu=Nq|Q2C!6J1PtIOt#ZVih-zr;oYPKVAr z9$2e|sy=B&9QHIWQq$lxkXUbctCY4l{nmC{icTF2l-afeYOjsPoYZW)jQd#8sr4bo zWzQ#jBvGpSxv(5hRA!o5lV4z)3T+SdYt>aVmK%y1tc~&zTJ^dUiLJ(wE2q6=#cl93 zysp}GNu?5PEMGKO^sGx)Oc=`!dXOfY-hO^g<*f89l(r|E+a)JJwJ~g$tK+dr-=?C0 zx>qtqS4AwI(gmYvh1FQNVmKa*GRv5M4P4U7P(T+=k#kq$eB?yo+i`ohHn7SvxQJ;RO$hNxrZ7d;HQz9~=tVMox1DM0gJCD- z?cP=+&rIIE1i9n~9NvY3%6eDeH!F2CX43SJfa{Sy~l*Ilg1gq!F8L>7Ix$5Km5wee+MZ!frE zSEv?P!UmiR!86+;M+LZUYy(Zrj39)tSv)FN%FQNRsC!G%ic3EX(@wRA@!DE0VTY@N zx4dnOBZkQ~wE0TOXG?lUHO2?0GElvgg4^|2qoGx+)`;Ch5%tw5NFv2ibH=Naaaw|{ zNj2f~4*0FL+Sr8JE=UD#Xjw!x*+dJnQbFB z&3wIF8zzprH<$HRwzy$3Esmpdq*<}C=pN@ONJb5Cn<+ix)>5OCYJu6S0Jq8Dt-t{zbjN1av7 zt%asWl^uC%$sZD#5^O=94bu~A!SL$2(M6hU+6j1>5! z-?5L&{c55x?iV=lXN9DPtlIp>5$iUiOrdMpMh%|qvYqv%H4TAqG9^=Q(XxrAjACE1 zhTJ-q(N9Sz*Qg_r)ygj|k#e3-&3T#dHHeanQ8k@yNA)x#zMfFTRkTFf*dXCAA%35; zWMWKa^T=mUR#1pvx);S^H`stB3{Q{X-rQ90_=yo`D_aK>YBM!x4be_9+!z(|=t}Aa zyv+^I%%|2_yVsxRj09A5tNhxcUm&h{1Pd2LnDuMh`bnJW>H2lv-ZR%^Q@^vFO_Pdc zxCo6)#!0sP1C2kD-)#guk+)MvtDhl%+b1gNh%w06}AUUA@3BPuloMJW7*cM zBh9&sl?%n7Z90u4Gx@2W4b&?Jn5LkK!!*jIwrw^gxmx8Z>g~s~t(Gh0K$ljEi7<$( zrVr`-7LCnSp&JE_2h<#K_xu@ucd&)^f^lYuohU-*e0p%2bk?Wmo;IJJ`{h1;tv%pd zlbPPSnMAx5Sm88<ZE#XvW=}!aq7~gs6v9(TVkFOx-r(pt)8z`OAQ*=7=6;9+aWlgvD_-OAb}DKMW3gT zcJ!EqU2Evzi)@`J*q83CegQZ8Qe(|6Y#!Wc)MY{r65aLk(OD(aR6D&fn&BZCH78as z!C2jDIV_=Jjd{=rO<4*Vt+{VSOo;}?)&m2YtH9Y{exda+ML!=AjctuZv)F8OLr6%r zb$(CQ!-b0(f!re55MuMNo@OOD9;B=DKm*OX(T3tcoJVl}V^} zpma?xq-@eG-8Y7Nriig(x3ZX90>=fuP+5=8;FPwgTTY66oXzNmsa0VX>eTIm)XST@ zxwz4UL7_Pna1(i9DE82SzEyUV11WBiUHVLwcG`p2QCaV;3`?>O?HE&~@+cEDPrO3I zDMS=>+zqYUP;eX$+M}>wZo>|aGc30!3gtP^ADl*<6UwK}^XGo4=WkcNS-x#BXs4z1 zW=&JtrPUOZgrL{aUB+l~?G?L|4w7nUjkCtw=>!jqR;iQ%>4M&vwv{iYr$}n3GX{DR ztWZmr0bhkDitLJGf>lAIfo^bCx5?&i!lVsnrF2^`ck*Jb+jI-iU^R<`gEMWhC;8)( zDe0bvot-h8DJ9c&aEjZ;O>MCjvla%cD9`|l?nMhR#cN4N(gNiWY ziSZRDGO0&5m?;u>;8bo73R0CC6I?%-!b?}V<1P@ISe<8V)@+8|6iiHKC6Azp#ZgD5 z+XSl&5H{7Nz|KhbEo?3!YE$*mDrQ9d;b9t-z!+smOQyBz^LA>ovX@qkgeDS9Q)Z~| z-WulCWdt0qb*GbMq$5|nUh8ny(?(kUt=T-)NxVFEM72@DXVk=aa{|t(g@UtdHYIf4 zoNfX65XV5{2)Mc%gB@=Vx(?QB4eF;3MF}9!giL7>U}*B*o0M6(c|;*3@<=c~o1tGG2}n>GV|qhyU|8U;G)(~SdU5U)2&qws)n`Z|GH*%z&*;{6g| z9hexU8}trp6@W`pu*!L_BCMjIM4?La@^3r%`mMGbbcrqu{@wrq^C$?$Qj zYq%gqn@7P_y*UnLW3!mQycx+evo^e_)k_nbcQEVQkZ5C5(8hHOEDBp-!Q)$^8I4L5 zr?eujajk8umlsa0Rg;Hgd%$ZodWx%A$O>1o?QJv9s!snHr%9=4O-4(3A2&0^bpz7M z&C_lT7uI*Ejs_uxb+4#Rl19j!m^nnYtU7}zyd17Ht(;R?m{r7=Xb+o7Gp+NF5KnIs z7?tSaM69|Qeo8bN_Ga3VH0vgI%M5DPaLOR9wD~S?tEN_qrVrK6s3m-&WS#Th@uv>R z!4~^8xn>x8q66QcdAo&AfYXbrsafVxy%f;<`M7c1D6XWDedcuAiHX%TH)gcJW$Aj- z<$<3;W9iOnSup!2@ zx3ZjiYT8bQmI{tq8&S){Q9cN~cwZ){bwIe+?hdHYc4VfwP|9klXokq5+}egDS!c4F zNXbU?gP2Q6SPMfj)u>tW@pPz0ua@?4H{Z6oB&eEIDB9mZv2cy)n@9O1GUCdG0n?O{ z+BDKNHna+z@cHDGi7ltQ(Qe#8s${<8P0)0|N;$bcw6HQ-E6iRr< zCrS2cQQAcv6#10Ph@nqg*ny!Z#~m7%UWqf{PP1uV`Fgms;Tm>%C%l$T!5O=(+2+(L zH^{|eYsnm5Pt zl>9o+2EqtJtU5I6z@nNty_#yucCiUc88)~6DmcGia5iN$qsMt?z9G!hB;g6twYuNl z>(x{GSt~*C8J~{vks3?QoitDpgHLwWjEru+gby4AJF&MQJ zy9Ica4_Vo|CN|F&`nh%rmXSox+v=oiMzgEQWh;s~0}X3id2SfS#i}@d=4RbraC5>L{^@vR%>EftZCkTk~mcwQ^Z!blQ}{ zEY?Wnds3yE?Ij(#1l^=V46?Gi^C{!dQLtD?IakgaAh+8wH4O~{HApt*U`N0nl_!Y4 z8F6s>DC4VWXsxiCZ6bqwc5RP2jCOzCJ$6`ot6Iub_tk4TlIDZqb-X>oBxoqM76G9; z8Hs`EAnW!wsSO=;Y{LQXnofl=R1oy~irwjmP_UwEd!D*wN+iA3`Lw{>Q>fb|LZz6C ztq*jF7<0`nX$CE4imqZ8SF!HO6I6;bl?_$sQY_Gkb=IB*$1^BAfOX+m)UCMM!8ja& z0vkEeMN1A}%+|>^=O=5%*Qj)}Qz z&Gl1$Kaa57l3wr&o+xw{x)4yoY{A#>WK+R{anO#XOKK3BCpO-})SOT>B$~Uh@_vq6KrPIt~QNfnk2%;devh~92+2?+V2!!um?|h?=ggJ! zj+XN(5t|@U``BdBN?{6jm}0?9Vwo?S8JzVhTRIs~8Uty?>$4?tJ%OagR4JLmqE%hw zHwF-7X*(X;DKE5{LQ)sV0)ZQu8nvNY$Zn)6I9U!PIj3R8ic^aN#D^|e3)#^?!j!Zx z%4LQ$a8%REPgf%4Br;iTLGTyt9dIe)3bf_}Le$1Z&Q51e7QJ&J6ZMq8 zfuT=Z%!Gl*qE7H-CC%Y&u3k$-^QUifVRP8MES1foK2e<@qLBo5bo~_{aKdu4l2&S| zIi4f8y>8w_`k-=Mj!PzAh-;JL8q@WR_HZ@@a}n=qx@ZmLEp5TToBOWX+}R0aYp6oC z2HJX1>jt-HczV@yji7XgQ#P>8BI#C0%c>XsL17k1MF*C!YG^bv_327#wC7lmuZR7d zrL2mnWQtmWOCp_{7LlPko=y%!)p^zyp7jeJ3UlHxUM~?9v#oEWiBz!7 zRZS)+)$1?1Y1?L@HOB%eO;fh!3gI z6}&UI8B=Dc>L90sP$idk=Q3&?%Nt3bqpdMv%f84lv_EIaDN-*hgNS-#fz9?#r0FH8 z041h~QFhf{nhH=^6li;9rm^#izZD6iU2^4iN;RJ&tifZFR#X0!=xV-WRk z7R@eS80sC7fZ+A^6a+$?OHYvV#B*XKlXRq~qeW#VEX3?8KCo8cOr)$u9TH1)P2-k* zB3SYPvx%+R8qrd8>DI@>GDyIx5p~97Cxu)~2{5`ABe=S{b+gx*lUZ-o21m`2Vc$_3 z5p!|0=#I23!~6S!zmxo-ByxLMa-&Q+Fm!1w)^{SPDBamI9`2mw2FC z;_Jq0O9X?9T!_rO2+H9>)25_#BD4)|uVzz7HRo|Hp0_Rewr!RQ7%9T+sX>^#%By%~ zY^bIQ@3b#y7XFnqF(Ps;lD81XNy}!(y=*TP*O?MrDjWbwKv*s@=G%pJA?79~7ATfk z=uH-y{35*<3N4)?l zL6fn?5uG-z+Tp5|FN|XrU)>v68R}TmA#S?vO&JdHOeYkWk=BvFiZr?@XQQ&2yc}ec zX`C`so*SVUGB=xxGae1Kwu7#;a2I2WLDS1so%}il*GQl`MKxPFk#C#Dy43gk>k zCDjznCS`57Wc8Kc#+a=|Itw}+c5~giCqs|jX*S2#wTz~>G-6(K-glV{u3VAs6hlUH z*VlkJTdxuFd%86==N-h;I-RTA!v&u~c2%sIc}sTlC0n)>*7NzkH0s6ZvRGTjqD!eZ zb8mwqjl@Iw&A{Xylx#6B6L9DKje=*LF~_HRQy>(VCyXOzn3dqkEL2pqgC2!Uw z#W7jznvz&^t9YS7#9^{TWsromoGYnvXqD5ts7Bt@&@GK*&dO448|%uOJT*-@9}r4N zByA?Gd_b~_?m;J;@n|7o7EiimXG3KzBUP}$<&&lDtXp0O8MEhW(d_Bn z3zg@!&aTwnwyUfTO#bdl?Z}&h&}h9Gft2jk0cl4M`s(TcoWS(dm#xjJDYlGp4Lws_do%|I2SXW2L(}FbNA~9#mH#Lp+WL57LLZ;0N)nZ3jC5Gsx?qqHI8q z!e}!E(}7mDGp!Drzf9)MH1!yh|tft2aplcqs+3sR*) zr^_8#86?Gn-?7s!$5E8dZbyd#P`F{C9Dw#mQ948$%ynk6^F{~HtL_pU&+cM}4R$8) z7Y~M?#^KB=iPH!Zr-9^|MW0?Zc&T-_80z%0pPF>{r0XwR5x(ni4v7%p`B9MpFEd~6 zNEFflepVchatS|cq8)|d2(aet>JEu~Zs1_{$N<1D6b93}VhqiGZ*!XKT3rg0F9 z@56TaWP31xN!LH!RUP$cZ_cwfgR%; zVEM82a@_7g>%H+fe0QRJbY70w-2$Hv1INzXPW_I;2y}Oew+F+SJz2xRZVcRuy><+~ zGXh8ZGUU!WAAtdtB==+kC=9-HJoeg=#Ibe+e!MS19`8%g$NK^X@5vC@AjzGHJUTB6 zG-(fpqdQA{v>jmO?!yL0`r;V7+Y*k#aCEm1@4;A*7q<`Nc3b_?b_BgI2f!Gh`?|1$ z?duzWvBWW4C>nfLVs8$LImS0|ElD41M>D%4jHCE5$7B-Nbc)$u8_gWECBRyd)V^E+ zsvKJfOB2WN<0zKe$AtqbxGzH-jqmF|#({P0&kJB+KRCKJj^=hx)E`+dfbH_rj>3S9 z@6(E7$YXNKF&ulW9Sf9Ue>^~hefi^9`k1cn%AoCY)qZjQBM_V;8^ z!hk)_H=5no4`8l= zeSHHk;`qEQah#?sNgl(G1$V&5<^^uvaoBMhu=M%3Y(TCM2x38$0|Lv@%YnN~pdjcD z)!hWw@5ro-lCr{3N~ePXquY_YB&*P5pJG|>|G$L>8))); /* load upper prescale bit */ + + IOWR_I2C_OPENCORES_CTR(base, I2C_OPENCORES_CTR_EN_MSK); /* turn on the core*/ + +} + +/**************************************************************** +int I2C_start + Sets the start bit and then sends the first byte which + is the address of the device + the write bit. +inputs + base = the base address of the component + add = address of I2C device + read = 1== read 0== write +return value + 0 if address is acknowledged + 1 if address was not acknowledged +15-OCT-07 initial release +*****************************************************************/ +int I2C_start(alt_u32 base, alt_u32 add, alt_u32 read) +{ +#ifdef I2C_DEBUG + printf(" Start I2C at 0x%x, \n\twith address 0x%x \n\tand read 0x%x \n\tand prescale 0x%x\n",base,add,read); +#endif + + /* transmit the address shifted by one and the read/write bit*/ + IOWR_I2C_OPENCORES_TXR(base, ((add<<1) + (0x1 & read))); + + /* set start and write bits which will start the transaction*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_STA_MSK | I2C_OPENCORES_CR_WR_MSK ); + + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now check to see if the address was acknowledged */ + if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK) + { +#ifdef I2C_DEBUG + printf("\tNOACK\n"); +#endif + return (I2C_NOACK); + } + else + { +#ifdef I2C_DEBUG + printf("\tACK\n"); +#endif + return (I2C_ACK); + } +} + +/**************************************************************** +int I2C_read + assumes that any addressing and start + has already been done. + reads one byte of data from the slave. on the last read + we don't acknowldge and set the stop bit. +inputs + base = the base address of the component + last = on the last read there must not be a ack + +return value + byte read back. +15-OCT-07 initial release +*****************************************************************/ +alt_u32 I2C_read(alt_u32 base,alt_u32 last) +{ +#ifdef I2C_DEBUG + printf(" Read I2C at 0x%x, \n\twith last0x%x\n",base,last); +#endif + if( last) + { + /* start a read and no ack and stop bit*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK | + I2C_OPENCORES_CR_NACK_MSK | I2C_OPENCORES_CR_STO_MSK); + } + else + { + /* start read*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK ); + } + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now read the data */ + return (IORD_I2C_OPENCORES_RXR(base)); + +} + +/**************************************************************** +int I2C_write + assumes that any addressing and start + has already been done. + writes one byte of data from the slave. + If last is set the stop bit set. +inputs + base = the base address of the component + data = byte to write + last = on the last read there must not be a ack + +return value + 0 if address is acknowledged + 1 if address was not acknowledged +15-OCT-07 initial release +*****************************************************************/ +alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last) +{ + #ifdef I2C_DEBUG + printf(" Read I2C at 0x%x, \n\twith data 0x%x,\n\twith last0x%x\n",base,data,last); +#endif + /* transmit the data*/ + IOWR_I2C_OPENCORES_TXR(base, data); + + if( last) + { + /* start a write with ack and stop bit*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK | + I2C_OPENCORES_CR_STO_MSK); + } + else + { + /* start write with ack */ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK ); + } + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now check to see if the address was acknowledged */ + if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK) + { +#ifdef I2C_DEBUG + printf("\tNOACK\n"); +#endif + return (I2C_NOACK); + } + else + { +#ifdef I2C_DEBUG + printf("\tACK\n"); +#endif + return (I2C_ACK); + } + +} + +alt_u32 SPI_read(alt_u32 base) +{ + /* start read*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK ); + + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now read the data */ + return (IORD_I2C_OPENCORES_RXR(base)); +} + +void SPI_write(alt_u32 base,alt_u8 data) { + /* transmit the data*/ + IOWR_I2C_OPENCORES_TXR(base, data); + + /* start write */ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK ); + + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); +} diff --git a/ip/i2c_opencores/i2c_master_bit_ctrl.v b/ip/i2c_opencores/i2c_master_bit_ctrl.v new file mode 100644 index 0000000..0b4f3b4 --- /dev/null +++ b/ip/i2c_opencores/i2c_master_bit_ctrl.v @@ -0,0 +1,621 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master bit-controller //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_bit_ctrl.v,v 1.11 2004/05/07 11:02:26 rherveille Exp $ +// +// $Date: 2004/05/07 11:02:26 $ +// $Revision: 1.11 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_bit_ctrl.v,v $ +// Revision 1.11 2004/05/07 11:02:26 rherveille +// Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. +// +// Revision 1.10 2003/08/09 07:01:33 rherveille +// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +// Fixed a potential bug in the byte controller's host-acknowledge generation. +// +// Revision 1.9 2003/03/10 14:26:37 rherveille +// Fixed cmd_ack generation item (no bug). +// +// Revision 1.8 2003/02/05 00:06:10 rherveille +// Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. +// +// Revision 1.7 2002/12/26 16:05:12 rherveille +// Small code simplifications +// +// Revision 1.6 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.5 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.4 2002/10/30 18:10:07 rherveille +// Fixed some reported minor start/stop generation timing issuess. +// +// Revision 1.3 2002/06/15 07:37:03 rherveille +// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. +// +// Revision 1.2 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + +// +///////////////////////////////////// +// Bit controller section +///////////////////////////////////// +// +// Translate simple commands into SCL/SDA transitions +// Each command has 5 states, A/B/C/D/idle +// +// start: SCL ~~~~~~~~~~\____ +// SDA ~~~~~~~~\______ +// x | A | B | C | D | i +// +// repstart SCL ____/~~~~\___ +// SDA __/~~~\______ +// x | A | B | C | D | i +// +// stop SCL ____/~~~~~~~~ +// SDA ==\____/~~~~~ +// x | A | B | C | D | i +// +//- write SCL ____/~~~~\____ +// SDA ==X=========X= +// x | A | B | C | D | i +// +//- read SCL ____/~~~~\____ +// SDA XXXX=====XXXX +// x | A | B | C | D | i +// + +// Timing: Normal mode Fast mode +/////////////////////////////////////////////////////////////////////// +// Fscl 100KHz 400KHz +// Th_scl 4.0us 0.6us High period of SCL +// Tl_scl 4.7us 1.3us Low period of SCL +// Tsu:sta 4.7us 0.6us setup time for a repeated start condition +// Tsu:sto 4.0us 0.6us setup time for a stop conditon +// Tbuf 4.7us 1.3us Bus free time between a stop and start condition +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_bit_ctrl( + clk, rst, nReset, + clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout, + scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen + ); + + // + // inputs & outputs + // + input clk; + input rst; + input nReset; + input ena; // core enable signal + + input [15:0] clk_cnt; // clock prescale value + + input [5:0] cmd; + output cmd_ack; // command complete acknowledge + reg cmd_ack; + output busy; // i2c bus busy + reg busy; + output al; // i2c bus arbitration lost + reg al; + + input din; + output dout; + reg dout; + + // I2C lines + input scl_i; // i2c clock line input + output scl_o; // i2c clock line output + output scl_oen; // i2c clock line output enable (active low) + reg scl_oen; + input sda_i; // i2c data line input + output sda_o; // i2c data line output + output sda_oen; // i2c data line output enable (active low) + reg sda_oen; + + + // + // variable declarations + // + + reg sSCL, sSDA; // synchronized SCL and SDA inputs + reg dscl_oen; // delayed scl_oen + reg sda_chk; // check SDA output (Multi-master arbitration) + reg clk_en; // clock generation signals + wire slave_wait; +// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation) + reg [15:0] cnt; // clock divider counter (synthesis) + + // state machine variable + reg [24:0] c_state; + + // + // module body + // + + // whenever the slave is not ready it can delay the cycle by pulling SCL low + // delay scl_oen + always @(posedge clk) + dscl_oen <= #1 scl_oen; + + assign slave_wait = dscl_oen && !sSCL; + + + // generate clk enable signal + always @(posedge clk or negedge nReset) + if(~nReset) + begin + cnt <= #1 16'h0; + clk_en <= #1 1'b1; + end + else if (rst) + begin + cnt <= #1 16'h0; + clk_en <= #1 1'b1; + end + else if ( ~|cnt || ~ena) + if (~slave_wait) + begin + cnt <= #1 clk_cnt; + clk_en <= #1 1'b1; + end + else + begin + cnt <= #1 cnt; + clk_en <= #1 1'b0; + end + else + begin + cnt <= #1 cnt - 16'h1; + clk_en <= #1 1'b0; + end + + + // generate bus status controller + reg dSCL, dSDA; + reg sta_condition; + reg sto_condition; + + // synchronize SCL and SDA inputs + // reduce metastability risc + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sSCL <= #1 1'b1; + sSDA <= #1 1'b1; + + dSCL <= #1 1'b1; + dSDA <= #1 1'b1; + end + else if (rst) + begin + sSCL <= #1 1'b1; + sSDA <= #1 1'b1; + + dSCL <= #1 1'b1; + dSDA <= #1 1'b1; + end + else + begin + sSCL <= #1 scl_i; + sSDA <= #1 sda_i; + + dSCL <= #1 sSCL; + dSDA <= #1 sSDA; + end + + // detect start condition => detect falling edge on SDA while SCL is high + // detect stop condition => detect rising edge on SDA while SCL is high + always @(posedge clk or negedge nReset) + if (~nReset) + begin + sta_condition <= #1 1'b0; + sto_condition <= #1 1'b0; + end + else if (rst) + begin + sta_condition <= #1 1'b0; + sto_condition <= #1 1'b0; + end + else + begin + sta_condition <= #1 ~sSDA & dSDA & sSCL; + sto_condition <= #1 sSDA & ~dSDA & sSCL; + end + + // generate i2c bus busy signal + always @(posedge clk or negedge nReset) + if(!nReset) + busy <= #1 1'b0; + else if (rst) + busy <= #1 1'b0; + else + busy <= #1 (sta_condition | busy) & ~sto_condition; + + // generate arbitration lost signal + // aribitration lost when: + // 1) master drives SDA high, but the i2c bus is low + // 2) stop detected while not requested + reg cmd_stop; + always @(posedge clk or negedge nReset) + if (~nReset) + cmd_stop <= #1 1'b0; + else if (rst) + cmd_stop <= #1 1'b0; + else if (clk_en) + cmd_stop <= #1 (cmd & (`I2C_CMD_STOP|`SPI_CMD_WRITE|`SPI_CMD_READ)) != 6'b000000; + + always @(posedge clk or negedge nReset) + if (~nReset) + al <= #1 1'b0; + else if (rst) + al <= #1 1'b0; + else + al <= #1 (sda_chk & ~sSDA & sda_oen) | (|c_state & sto_condition & ~cmd_stop); + + + // generate dout signal (store SDA on rising edge of SCL) + always @(posedge clk) + if(sSCL & ~dSCL) + dout <= #1 sSDA; + + // generate statemachine + + // nxt_state decoder + parameter [24:0] idle = 25'b0_0000_0000_0000_0000_0000_0000; + parameter [24:0] start_a = 25'b0_0000_0000_0000_0000_0000_0001; + parameter [24:0] start_b = 25'b0_0000_0000_0000_0000_0000_0010; + parameter [24:0] start_c = 25'b0_0000_0000_0000_0000_0000_0100; + parameter [24:0] start_d = 25'b0_0000_0000_0000_0000_0000_1000; + parameter [24:0] start_e = 25'b0_0000_0000_0000_0000_0001_0000; + parameter [24:0] stop_a = 25'b0_0000_0000_0000_0000_0010_0000; + parameter [24:0] stop_b = 25'b0_0000_0000_0000_0000_0100_0000; + parameter [24:0] stop_c = 25'b0_0000_0000_0000_0000_1000_0000; + parameter [24:0] stop_d = 25'b0_0000_0000_0000_0001_0000_0000; + parameter [24:0] rd_a = 25'b0_0000_0000_0000_0010_0000_0000; + parameter [24:0] rd_b = 25'b0_0000_0000_0000_0100_0000_0000; + parameter [24:0] rd_c = 25'b0_0000_0000_0000_1000_0000_0000; + parameter [24:0] rd_d = 25'b0_0000_0000_0001_0000_0000_0000; + parameter [24:0] wr_a = 25'b0_0000_0000_0010_0000_0000_0000; + parameter [24:0] wr_b = 25'b0_0000_0000_0100_0000_0000_0000; + parameter [24:0] wr_c = 25'b0_0000_0000_1000_0000_0000_0000; + parameter [24:0] wr_d = 25'b0_0000_0001_0000_0000_0000_0000; + + parameter [24:0] spi_rd_a = 25'b0_0000_0010_0000_0000_0000_0000; + parameter [24:0] spi_rd_b = 25'b0_0000_0100_0000_0000_0000_0000; + parameter [24:0] spi_rd_c = 25'b0_0000_1000_0000_0000_0000_0000; + parameter [24:0] spi_rd_d = 25'b0_0001_0000_0000_0000_0000_0000; + parameter [24:0] spi_wr_a = 25'b0_0010_0000_0000_0000_0000_0000; + parameter [24:0] spi_wr_b = 25'b0_0100_0000_0000_0000_0000_0000; + parameter [24:0] spi_wr_c = 25'b0_1000_0000_0000_0000_0000_0000; + parameter [24:0] spi_wr_d = 25'b1_0000_0000_0000_0000_0000_0000; + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b0; + scl_oen <= #1 1'b1; + sda_oen <= #1 1'b1; + sda_chk <= #1 1'b0; + end + else if (rst | al) + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b0; + scl_oen <= #1 1'b1; + sda_oen <= #1 1'b1; + sda_chk <= #1 1'b0; + end + else + begin + cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle + + if (clk_en) + case (c_state) + // idle state + idle: + begin + case (cmd) + `I2C_CMD_START: + c_state <= #1 start_a; + + `I2C_CMD_STOP: + c_state <= #1 stop_a; + + `I2C_CMD_WRITE: + c_state <= #1 wr_a; + + `I2C_CMD_READ: + c_state <= #1 rd_a; + + `SPI_CMD_WRITE: + c_state <= #1 spi_wr_a; + + `SPI_CMD_READ: + c_state <= #1 spi_rd_a; + + default: + c_state <= #1 idle; + endcase + + scl_oen <= #1 scl_oen; // keep SCL in same state + sda_oen <= #1 sda_oen; // keep SDA in same state + sda_chk <= #1 1'b0; // don't check SDA output + end + + // start + start_a: + begin + c_state <= #1 start_b; + scl_oen <= #1 scl_oen; // keep SCL in same state + sda_oen <= #1 1'b1; // set SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_b: + begin + c_state <= #1 start_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_c: + begin + c_state <= #1 start_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // set SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_d: + begin + c_state <= #1 start_e; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + start_e: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + // stop + stop_a: + begin + c_state <= #1 stop_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b0; // set SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_b: + begin + c_state <= #1 stop_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_c: + begin + c_state <= #1 stop_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b0; // keep SDA low + sda_chk <= #1 1'b0; // don't check SDA output + end + + stop_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b1; // set SDA high + sda_chk <= #1 1'b0; // don't check SDA output + end + + // read + rd_a: + begin + c_state <= #1 rd_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b1; // tri-state SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_b: + begin + c_state <= #1 rd_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_c: + begin + c_state <= #1 rd_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + rd_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + // write + wr_a: + begin + c_state <= #1 wr_b; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 din; // set SDA + sda_chk <= #1 1'b0; // don't check SDA output (SCL low) + end + + wr_b: + begin + c_state <= #1 wr_c; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 din; // keep SDA + sda_chk <= #1 1'b1; // check SDA output + end + + wr_c: + begin + c_state <= #1 wr_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 din; + sda_chk <= #1 1'b1; // check SDA output + end + + wr_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 din; + sda_chk <= #1 1'b0; // don't check SDA output (SCL low) + end + + // read (last SPI bit) + spi_rd_a: + begin + c_state <= #1 spi_rd_b; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b1; // tri-state SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + spi_rd_b: + begin + c_state <= #1 spi_rd_c; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + spi_rd_c: + begin + c_state <= #1 spi_rd_d; + scl_oen <= #1 1'b1; // set SCL high + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + spi_rd_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b1; // tri-state SCL + sda_oen <= #1 1'b1; // keep SDA tri-stated + sda_chk <= #1 1'b0; // don't check SDA output + end + + // write (last SPI bit) + spi_wr_a: + begin + c_state <= #1 spi_wr_b; + scl_oen <= #1 1'b0; // set SCL low + sda_oen <= #1 1'b1; // keep SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + spi_wr_b: + begin + c_state <= #1 spi_wr_c; + scl_oen <= #1 1'b0; // keep SCL low + sda_oen <= #1 din; // set SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + spi_wr_c: + begin + c_state <= #1 spi_wr_d; + scl_oen <= #1 1'b1; // keep SCL high + sda_oen <= #1 din; // keep SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + spi_wr_d: + begin + c_state <= #1 idle; + cmd_ack <= #1 1'b1; + scl_oen <= #1 1'b1; // tri-state SCL + sda_oen <= #1 1'b1; // tri-state SDA + sda_chk <= #1 1'b0; // don't check SDA output + end + + default: + c_state <= #1 idle; + + endcase + end + + + // assign scl and sda output (always gnd) + assign scl_o = 1'b0; + assign sda_o = 1'b0; + +endmodule diff --git a/ip/i2c_opencores/i2c_master_byte_ctrl.v b/ip/i2c_opencores/i2c_master_byte_ctrl.v new file mode 100644 index 0000000..2ba4ed5 --- /dev/null +++ b/ip/i2c_opencores/i2c_master_byte_ctrl.v @@ -0,0 +1,382 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master byte-controller //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_byte_ctrl.v,v 1.7 2004/02/18 11:40:46 rherveille Exp $ +// +// $Date: 2004/02/18 11:40:46 $ +// $Revision: 1.7 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_byte_ctrl.v,v $ +// Revision 1.7 2004/02/18 11:40:46 rherveille +// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command. +// +// Revision 1.6 2003/08/09 07:01:33 rherveille +// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +// Fixed a potential bug in the byte controller's host-acknowledge generation. +// +// Revision 1.5 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.4 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.3 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_byte_ctrl ( + clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, spi_mode, din, + cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); + + // + // inputs & outputs + // + input clk; // master clock + input rst; // synchronous active high reset + input nReset; // asynchronous active low reset + input ena; // core enable signal + + input [15:0] clk_cnt; // 4x SCL + + // control inputs + input start; + input stop; + input read; + input write; + input ack_in; + input spi_mode; + input [7:0] din; + + // status outputs + output cmd_ack; + reg cmd_ack; + output ack_out; + reg ack_out; + output i2c_busy; + output i2c_al; + output [7:0] dout; + + // I2C signals + input scl_i; + output scl_o; + output scl_oen; + input sda_i; + output sda_o; + output sda_oen; + + + // + // Variable declarations + // + + // statemachine + parameter [6:0] ST_IDLE = 7'b000_0000; + parameter [6:0] ST_START = 7'b000_0001; + parameter [6:0] ST_READ = 7'b000_0010; + parameter [6:0] ST_WRITE = 7'b000_0100; + parameter [6:0] ST_ACK = 7'b000_1000; + parameter [6:0] ST_STOP = 7'b001_0000; + parameter [6:0] ST_SPI_READ = 7'b010_0000; + parameter [6:0] ST_SPI_WRITE = 7'b100_0000; + + + // signals for bit_controller + reg [5:0] core_cmd; + reg core_txd; + wire core_ack, core_rxd; + + // signals for shift register + reg [7:0] sr; //8bit shift register + reg shift, ld; + + // signals for state machine + wire go; + reg [2:0] dcnt; + wire cnt_done; + + // + // Module body + // + + // hookup bit_controller + i2c_master_bit_ctrl bit_controller ( + .clk ( clk ), + .rst ( rst ), + .nReset ( nReset ), + .ena ( ena ), + .clk_cnt ( clk_cnt ), + .cmd ( core_cmd ), + .cmd_ack ( core_ack ), + .busy ( i2c_busy ), + .al ( i2c_al ), + .din ( core_txd ), + .dout ( core_rxd ), + .scl_i ( scl_i ), + .scl_o ( scl_o ), + .scl_oen ( scl_oen ), + .sda_i ( sda_i ), + .sda_o ( sda_o ), + .sda_oen ( sda_oen ) + ); + + // generate go-signal + assign go = (read | write | stop) & ~cmd_ack; + + // assign dout output to shift-register + assign dout = sr; + + // generate shift register + always @(posedge clk or negedge nReset) + if (!nReset) + sr <= #1 8'h0; + else if (rst) + sr <= #1 8'h0; + else if (ld) + sr <= #1 din; + else if (shift) + sr <= #1 {sr[6:0], core_rxd}; + + // generate counter + always @(posedge clk or negedge nReset) + if (!nReset) + dcnt <= #1 3'h0; + else if (rst) + dcnt <= #1 3'h0; + else if (ld) + dcnt <= #1 3'h7; + else if (shift) + dcnt <= #1 dcnt - 3'h1; + + assign cnt_done = ~(|dcnt); + + // + // state machine + // + reg [6:0] c_state; // synopsis enum_state + + always @(posedge clk or negedge nReset) + if (!nReset) + begin + core_cmd <= #1 `I2C_CMD_NOP; + core_txd <= #1 1'b0; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + c_state <= #1 ST_IDLE; + ack_out <= #1 1'b0; + end + else if (rst | i2c_al) + begin + core_cmd <= #1 `I2C_CMD_NOP; + core_txd <= #1 1'b0; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + c_state <= #1 ST_IDLE; + ack_out <= #1 1'b0; + end + else + begin + // initially reset all signals + core_txd <= #1 sr[7]; + shift <= #1 1'b0; + ld <= #1 1'b0; + cmd_ack <= #1 1'b0; + + case (c_state) // synopsys full_case parallel_case + ST_IDLE: + if (go) + begin + if (start) + begin + c_state <= #1 ST_START; + core_cmd <= #1 `I2C_CMD_START; + end + else if (read) + begin + c_state <= #1 spi_mode ? ST_SPI_READ : ST_READ; + core_cmd <= #1 spi_mode ? `SPI_CMD_READ : `I2C_CMD_READ; + end + else if (write) + begin + c_state <= #1 spi_mode ? ST_SPI_WRITE : ST_WRITE; + core_cmd <= #1 spi_mode ? `SPI_CMD_WRITE : `I2C_CMD_WRITE; + end + else // stop + begin + c_state <= #1 ST_STOP; + core_cmd <= #1 `I2C_CMD_STOP; + end + + ld <= #1 1'b1; + end + + ST_START: + if (core_ack) + begin + if (read) + begin + c_state <= #1 ST_READ; + core_cmd <= #1 `I2C_CMD_READ; + end + else + begin + c_state <= #1 ST_WRITE; + core_cmd <= #1 `I2C_CMD_WRITE; + end + + ld <= #1 1'b1; + end + + ST_WRITE: + if (core_ack) + if (cnt_done) + begin + c_state <= #1 ST_ACK; + core_cmd <= #1 `I2C_CMD_READ; + end + else + begin + c_state <= #1 ST_WRITE; // stay in same state + core_cmd <= #1 `I2C_CMD_WRITE; // write next bit + shift <= #1 1'b1; + end + + ST_READ: + if (core_ack) + begin + if (cnt_done) + begin + c_state <= #1 ST_ACK; + core_cmd <= #1 `I2C_CMD_WRITE; + end + else + begin + c_state <= #1 ST_READ; // stay in same state + core_cmd <= #1 `I2C_CMD_READ; // read next bit + end + + shift <= #1 1'b1; + core_txd <= #1 ack_in; + end + + ST_ACK: + if (core_ack) + begin + if (stop) + begin + c_state <= #1 ST_STOP; + core_cmd <= #1 `I2C_CMD_STOP; + end + else + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= #1 1'b1; + end + + // assign ack_out output to bit_controller_rxd (contains last received bit) + ack_out <= #1 core_rxd; + + core_txd <= #1 1'b1; + end + else + core_txd <= #1 ack_in; + + ST_STOP: + if (core_ack) + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + + // generate command acknowledge signal + cmd_ack <= #1 1'b1; + end + + ST_SPI_WRITE: + if (core_ack) + if (cnt_done) + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + cmd_ack <= #1 1'b1; + end + else + begin + c_state <= #1 ST_SPI_WRITE; // stay in same state + core_cmd <= #1 `SPI_CMD_WRITE; // write next bit + shift <= #1 1'b1; + end + + ST_SPI_READ: + if (core_ack) + begin + if (cnt_done) + begin + c_state <= #1 ST_IDLE; + core_cmd <= #1 `I2C_CMD_NOP; + cmd_ack <= #1 1'b1; + end + else + begin + c_state <= #1 ST_SPI_READ; // stay in same state + core_cmd <= #1 `SPI_CMD_READ; // read next bit + end + + shift <= #1 1'b1; + core_txd <= #1 ack_in; + end + + endcase + end +endmodule diff --git a/ip/i2c_opencores/i2c_master_defines.v b/ip/i2c_opencores/i2c_master_defines.v new file mode 100644 index 0000000..4f2f17f --- /dev/null +++ b/ip/i2c_opencores/i2c_master_defines.v @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE rev.B2 compliant I2C Master controller defines //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_defines.v,v 1.3 2001/11/05 11:59:25 rherveille Exp $ +// +// $Date: 2001/11/05 11:59:25 $ +// $Revision: 1.3 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_defines.v,v $ +// Revision 1.3 2001/11/05 11:59:25 rherveille +// Fixed wb_ack_o generation bug. +// Fixed bug in the byte_controller statemachine. +// Added headers. +// + + +// I2C registers wishbone addresses + +// bitcontroller states +`define I2C_CMD_NOP 6'b000000 +`define I2C_CMD_START 6'b000001 +`define I2C_CMD_STOP 6'b000010 +`define I2C_CMD_WRITE 6'b000100 +`define I2C_CMD_READ 6'b001000 +`define SPI_CMD_WRITE 6'b010000 +`define SPI_CMD_READ 6'b100000 diff --git a/ip/i2c_opencores/i2c_master_top.v b/ip/i2c_opencores/i2c_master_top.v new file mode 100644 index 0000000..bc2dccd --- /dev/null +++ b/ip/i2c_opencores/i2c_master_top.v @@ -0,0 +1,300 @@ +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE revB.2 compliant I2C Master controller Top-level //// +//// //// +//// //// +//// Author: Richard Herveille //// +//// richard@asics.ws //// +//// www.asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/projects/i2c/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2001 Richard Herveille //// +//// richard@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// CVS Log +// +// $Id: i2c_master_top.v,v 1.10 2003/09/01 10:34:38 rherveille Exp $ +// +// $Date: 2003/09/01 10:34:38 $ +// $Revision: 1.10 $ +// $Author: rherveille $ +// $Locker: $ +// $State: Exp $ +// +// Change History: +// $Log: i2c_master_top.v,v $ +// Revision 1.10 2003/09/01 10:34:38 rherveille +// Fix a blocking vs. non-blocking error in the wb_dat output mux. +// +// Revision 1.9 2003/01/09 16:44:45 rherveille +// Fixed a bug in the Command Register declaration. +// +// Revision 1.8 2002/12/26 16:05:12 rherveille +// Small code simplifications +// +// Revision 1.7 2002/12/26 15:02:32 rherveille +// Core is now a Multimaster I2C controller +// +// Revision 1.6 2002/11/30 22:24:40 rherveille +// Cleaned up code +// +// Revision 1.5 2001/11/10 10:52:55 rherveille +// Changed PRER reset value from 0x0000 to 0xffff, conform specs. +// + +// synopsys translate_off +`include "timescale.v" +// synopsys translate_on + +`include "i2c_master_defines.v" + +module i2c_master_top( + wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, + wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o, + scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); + + // parameters + parameter ARST_LVL = 1'b0; // asynchronous reset level + + // + // inputs & outputs + // + + // wishbone signals + input wb_clk_i; // master clock input + input wb_rst_i; // synchronous active high reset + input arst_i; // asynchronous reset + input [2:0] wb_adr_i; // lower address bits + input [7:0] wb_dat_i; // databus input + output [7:0] wb_dat_o; // databus output + input wb_we_i; // write enable input + input wb_stb_i; // stobe/core select signal + input wb_cyc_i; // valid bus cycle input + output wb_ack_o; // bus cycle acknowledge output + output wb_inta_o; // interrupt request signal output + + reg [7:0] wb_dat_o; + reg wb_ack_o; + reg wb_inta_o; + + // I2C signals + // i2c clock line + input scl_pad_i; // SCL-line input + output scl_pad_o; // SCL-line output (always 1'b0) + output scl_padoen_o; // SCL-line output enable (active low) + + // i2c data line + input sda_pad_i; // SDA-line input + output sda_pad_o; // SDA-line output (always 1'b0) + output sda_padoen_o; // SDA-line output enable (active low) + + + // + // variable declarations + // + + // registers + reg [15:0] prer; // clock prescale register + reg [ 7:0] ctr; // control register + reg [ 7:0] txr; // transmit register + wire [ 7:0] rxr; // receive register + reg [ 7:0] cr; // command register + wire [ 7:0] sr; // status register + + // done signal: command completed, clear command register + wire done; + + // core enable signal + wire core_en; + wire ien; + + // status register signals + wire irxack; + reg rxack; // received aknowledge from slave + reg tip; // transfer in progress + reg irq_flag; // interrupt pending flag + wire i2c_busy; // bus busy (start signal detected) + wire i2c_al; // i2c bus arbitration lost + reg al; // status register arbitration lost bit + + // + // module body + // + + // generate internal reset + wire rst_i = arst_i ^ ARST_LVL; + + // generate wishbone signals + wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i; + + // generate acknowledge output signal + always @(posedge wb_clk_i) + wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored + + // assign DAT_O + always @(posedge wb_clk_i) + begin + case (wb_adr_i) // synopsis full_case parallel_case + 3'b000: wb_dat_o <= #1 prer[ 7:0]; + 3'b001: wb_dat_o <= #1 prer[15:8]; + 3'b010: wb_dat_o <= #1 ctr; + 3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr) + 3'b100: wb_dat_o <= #1 sr; // write is command register (cr) + 3'b101: wb_dat_o <= #1 txr; + 3'b110: wb_dat_o <= #1 cr; + 3'b111: wb_dat_o <= #1 0; // reserved + endcase + end + + // generate registers + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + prer <= #1 16'hffff; + ctr <= #1 8'h0; + txr <= #1 8'h0; + end + else if (wb_rst_i) + begin + prer <= #1 16'hffff; + ctr <= #1 8'h0; + txr <= #1 8'h0; + end + else + if (wb_wacc) + case (wb_adr_i) // synopsis full_case parallel_case + 3'b000 : prer [ 7:0] <= #1 wb_dat_i; + 3'b001 : prer [15:8] <= #1 wb_dat_i; + 3'b010 : ctr <= #1 wb_dat_i; + 3'b011 : txr <= #1 wb_dat_i; + endcase + + // generate command register (special case) + always @(posedge wb_clk_i or negedge rst_i) + if (~rst_i) + cr <= #1 8'h0; + else if (wb_rst_i) + cr <= #1 8'h0; + else if (wb_wacc) + begin + if (core_en & (wb_adr_i == 3'b100) ) + cr <= #1 wb_dat_i; + end + else + begin + if (done | i2c_al) + begin + cr[7:4] <= #1 4'h0; // clear command bits when done + cr[2] <= #1 1'b0; // or when aribitration lost + end + cr[1] <= #1 1'b0; // reserved bit + cr[0] <= #1 1'b0; // clear IRQ_ACK bit + end + + + // decode command register + wire sta = cr[7]; + wire sto = cr[6]; + wire rd = cr[5]; + wire wr = cr[4]; + wire ack = cr[3]; + wire spi = cr[2]; + wire iack = cr[0]; + + // decode control register + assign core_en = ctr[7]; + assign ien = ctr[6]; + + // hookup byte controller block + i2c_master_byte_ctrl byte_controller ( + .clk ( wb_clk_i ), + .rst ( wb_rst_i ), + .nReset ( rst_i ), + .ena ( core_en ), + .clk_cnt ( prer ), + .start ( sta ), + .stop ( sto ), + .read ( rd ), + .write ( wr ), + .ack_in ( ack ), + .spi_mode ( spi ), + .din ( txr ), + .cmd_ack ( done ), + .ack_out ( irxack ), + .dout ( rxr ), + .i2c_busy ( i2c_busy ), + .i2c_al ( i2c_al ), + .scl_i ( scl_pad_i ), + .scl_o ( scl_pad_o ), + .scl_oen ( scl_padoen_o ), + .sda_i ( sda_pad_i ), + .sda_o ( sda_pad_o ), + .sda_oen ( sda_padoen_o ) + ); + + // status register block + interrupt request signal + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + begin + al <= #1 1'b0; + rxack <= #1 1'b0; + tip <= #1 1'b0; + irq_flag <= #1 1'b0; + end + else if (wb_rst_i) + begin + al <= #1 1'b0; + rxack <= #1 1'b0; + tip <= #1 1'b0; + irq_flag <= #1 1'b0; + end + else + begin + al <= #1 i2c_al | (al & ~sta); + rxack <= #1 irxack; + tip <= #1 (rd | wr); + irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated + end + + // generate interrupt request signals + always @(posedge wb_clk_i or negedge rst_i) + if (!rst_i) + wb_inta_o <= #1 1'b0; + else if (wb_rst_i) + wb_inta_o <= #1 1'b0; + else + wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) + + // assign status register bits + assign sr[7] = rxack; + assign sr[6] = i2c_busy; + assign sr[5] = al; + assign sr[4:2] = 3'h0; // reserved + assign sr[1] = tip; + assign sr[0] = irq_flag; + +endmodule diff --git a/ip/i2c_opencores/i2c_opencores.v b/ip/i2c_opencores/i2c_opencores.v new file mode 100644 index 0000000..81dcdf8 --- /dev/null +++ b/ip/i2c_opencores/i2c_opencores.v @@ -0,0 +1,72 @@ +// +// fixed for 9.1 jan 21 2010 cruben +// +`include "timescale.v" +`include "i2c_master_defines.v" + +module i2c_opencores +( + wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, + wb_we_i, wb_stb_i, /*wb_cyc_i,*/ wb_ack_o, wb_inta_o, + scl_pad_io, sda_pad_io +); + + +// Common bus signals +input wb_clk_i; // WISHBONE clock +input wb_rst_i; // WISHBONE reset + +// Slave signals +input [2:0] wb_adr_i; // WISHBONE address input +input [7:0] wb_dat_i; // WISHBONE data input +output [7:0] wb_dat_o; // WISHBONE data output +input wb_we_i; // WISHBONE write enable input +input wb_stb_i; // WISHBONE strobe input +//input wb_cyc_i; // WISHBONE cycle input +output wb_ack_o; // WISHBONE acknowledge output +output wb_inta_o; // WISHBONE interrupt output + +// I2C signals +inout scl_pad_io; // I2C clock io +inout sda_pad_io; // I2C data io + +wire wb_cyc_i; // WISHBONE cycle input +// Wire tri-state scl/sda +wire scl_pad_i; +wire scl_pad_o; +wire scl_pad_io; +wire scl_padoen_o; + +assign wb_cyc_i = wb_stb_i; +assign scl_pad_i = scl_pad_io; +assign scl_pad_io = scl_padoen_o ? 1'bZ : scl_pad_o; + +wire sda_pad_i; +wire sda_pad_o; +wire sda_pad_io; +wire sda_padoen_o; + +assign sda_pad_i = sda_pad_io; +assign sda_pad_io = sda_padoen_o ? 1'bZ : sda_pad_o; + +// Avalon doesn't have an asynchronous reset +// set it to be inactive and just use synchronous reset +// reset level is a parameter, 0 is the default (active-low reset) +wire arst_i; + +assign arst_i = 1'b1; + +// Connect the top level I2C core +i2c_master_top i2c_master_top_inst +( + .wb_clk_i(wb_clk_i), .wb_rst_i(wb_rst_i), .arst_i(arst_i), + + .wb_adr_i(wb_adr_i), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o), + .wb_we_i(wb_we_i), .wb_stb_i(wb_stb_i), .wb_cyc_i(wb_cyc_i), + .wb_ack_o(wb_ack_o), .wb_inta_o(wb_inta_o), + + .scl_pad_i(scl_pad_i), .scl_pad_o(scl_pad_o), .scl_padoen_o(scl_padoen_o), + .sda_pad_i(sda_pad_i), .sda_pad_o(sda_pad_o), .sda_padoen_o(sda_padoen_o) +); + +endmodule diff --git a/ip/i2c_opencores/i2c_opencores_hw.tcl b/ip/i2c_opencores/i2c_opencores_hw.tcl new file mode 100644 index 0000000..8c28b2e --- /dev/null +++ b/ip/i2c_opencores/i2c_opencores_hw.tcl @@ -0,0 +1,166 @@ +# TCL File Generated by Component Editor 13.1 +# Sat May 17 17:29:02 EEST 2014 +# DO NOT MODIFY + + +# +# i2c_opencores "I2C Master (opencores.org)" v13.0 +# 2014.05.17.17:29:02 +# I2C Master Peripheral from opencores.org +# + +# +# request TCL package from ACDS 13.1 +# +package require -exact qsys 13.1 + + +# +# module i2c_opencores +# +set_module_property DESCRIPTION "I2C Master Peripheral from opencores.org" +set_module_property NAME i2c_opencores +set_module_property VERSION 13.0 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property GROUP "Interface Protocols/Serial" +set_module_property AUTHOR "" +set_module_property DISPLAY_NAME "I2C Master (opencores.org)" +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE true +set_module_property ANALYZE_HDL AUTO +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false + + +# +# file sets +# +add_fileset quartus_synth QUARTUS_SYNTH "" "Quartus Synthesis" +set_fileset_property quartus_synth TOP_LEVEL i2c_opencores +set_fileset_property quartus_synth ENABLE_RELATIVE_INCLUDE_PATHS false +add_fileset_file i2c_opencores.v VERILOG PATH i2c_opencores.v +add_fileset_file i2c_master_top.v VERILOG PATH i2c_master_top.v +add_fileset_file i2c_master_defines.v VERILOG PATH i2c_master_defines.v +add_fileset_file i2c_master_byte_ctrl.v VERILOG PATH i2c_master_byte_ctrl.v +add_fileset_file i2c_master_bit_ctrl.v VERILOG PATH i2c_master_bit_ctrl.v + +add_fileset sim_verilog SIM_VERILOG "" "Verilog Simulation" +set_fileset_property sim_verilog TOP_LEVEL i2c_opencores +set_fileset_property sim_verilog ENABLE_RELATIVE_INCLUDE_PATHS false +add_fileset_file i2c_opencores.v VERILOG PATH i2c_opencores.v +add_fileset_file i2c_master_top.v VERILOG PATH i2c_master_top.v +add_fileset_file i2c_master_defines.v VERILOG PATH i2c_master_defines.v +add_fileset_file i2c_master_byte_ctrl.v VERILOG PATH i2c_master_byte_ctrl.v +add_fileset_file i2c_master_bit_ctrl.v VERILOG PATH i2c_master_bit_ctrl.v +add_fileset_file timescale.v VERILOG PATH timescale.v + + +# +# parameters +# + + +# +# display items +# + + +# +# connection point clock +# +add_interface clock clock end +set_interface_property clock clockRate 0 +set_interface_property clock ENABLED true +set_interface_property clock EXPORT_OF "" +set_interface_property clock PORT_NAME_MAP "" +set_interface_property clock CMSIS_SVD_VARIABLES "" +set_interface_property clock SVD_ADDRESS_GROUP "" + +add_interface_port clock wb_clk_i clk Input 1 + + +# +# connection point clock_reset +# +add_interface clock_reset reset end +set_interface_property clock_reset associatedClock clock +set_interface_property clock_reset synchronousEdges DEASSERT +set_interface_property clock_reset ENABLED true +set_interface_property clock_reset EXPORT_OF "" +set_interface_property clock_reset PORT_NAME_MAP "" +set_interface_property clock_reset CMSIS_SVD_VARIABLES "" +set_interface_property clock_reset SVD_ADDRESS_GROUP "" + +add_interface_port clock_reset wb_rst_i reset Input 1 + + +# +# connection point export +# +add_interface export conduit end +set_interface_property export associatedClock "" +set_interface_property export associatedReset "" +set_interface_property export ENABLED true +set_interface_property export EXPORT_OF "" +set_interface_property export PORT_NAME_MAP "" +set_interface_property export CMSIS_SVD_VARIABLES "" +set_interface_property export SVD_ADDRESS_GROUP "" + +add_interface_port export scl_pad_io export Bidir 1 +add_interface_port export sda_pad_io export Bidir 1 + + +# +# connection point avalon_slave_0 +# +add_interface avalon_slave_0 avalon end +set_interface_property avalon_slave_0 addressAlignment NATIVE +set_interface_property avalon_slave_0 addressUnits WORDS +set_interface_property avalon_slave_0 associatedClock clock +set_interface_property avalon_slave_0 associatedReset clock_reset +set_interface_property avalon_slave_0 bitsPerSymbol 8 +set_interface_property avalon_slave_0 burstOnBurstBoundariesOnly false +set_interface_property avalon_slave_0 burstcountUnits WORDS +set_interface_property avalon_slave_0 explicitAddressSpan 0 +set_interface_property avalon_slave_0 holdTime 0 +set_interface_property avalon_slave_0 linewrapBursts false +set_interface_property avalon_slave_0 maximumPendingReadTransactions 0 +set_interface_property avalon_slave_0 readLatency 0 +set_interface_property avalon_slave_0 readWaitTime 1 +set_interface_property avalon_slave_0 setupTime 0 +set_interface_property avalon_slave_0 timingUnits Cycles +set_interface_property avalon_slave_0 writeWaitTime 0 +set_interface_property avalon_slave_0 ENABLED true +set_interface_property avalon_slave_0 EXPORT_OF "" +set_interface_property avalon_slave_0 PORT_NAME_MAP "" +set_interface_property avalon_slave_0 CMSIS_SVD_VARIABLES "" +set_interface_property avalon_slave_0 SVD_ADDRESS_GROUP "" + +add_interface_port avalon_slave_0 wb_adr_i address Input 3 +add_interface_port avalon_slave_0 wb_dat_i writedata Input 8 +add_interface_port avalon_slave_0 wb_dat_o readdata Output 8 +add_interface_port avalon_slave_0 wb_we_i write Input 1 +add_interface_port avalon_slave_0 wb_stb_i chipselect Input 1 +add_interface_port avalon_slave_0 wb_ack_o waitrequest_n Output 1 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isFlash 0 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isMemoryDevice 0 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isNonVolatileStorage 0 +set_interface_assignment avalon_slave_0 embeddedsw.configuration.isPrintableDevice 0 + + +# +# connection point interrupt_sender +# +add_interface interrupt_sender interrupt end +set_interface_property interrupt_sender associatedAddressablePoint avalon_slave_0 +set_interface_property interrupt_sender associatedClock clock +set_interface_property interrupt_sender associatedReset clock_reset +set_interface_property interrupt_sender ENABLED true +set_interface_property interrupt_sender EXPORT_OF "" +set_interface_property interrupt_sender PORT_NAME_MAP "" +set_interface_property interrupt_sender CMSIS_SVD_VARIABLES "" +set_interface_property interrupt_sender SVD_ADDRESS_GROUP "" + +add_interface_port interrupt_sender wb_inta_o irq Output 1 + diff --git a/ip/i2c_opencores/i2c_opencores_sw.tcl b/ip/i2c_opencores/i2c_opencores_sw.tcl new file mode 100644 index 0000000..e439154 --- /dev/null +++ b/ip/i2c_opencores/i2c_opencores_sw.tcl @@ -0,0 +1,56 @@ +# +# opencores_i2c_sw.tcl +# + +# Create a new driver +create_driver i2c_opencores_driver + +# Associate it with some hardware known as "opencores_i2c" +set_sw_property hw_class_name i2c_opencores + +# The version of this driver +set_sw_property version 11.0 + +# This driver may be incompatible with versions of hardware less +# than specified below. Updates to hardware and device drivers +# rendering the driver incompatible with older versions of +# hardware are noted with this property assignment. +# +# Multiple-Version compatibility was introduced in version 7.1; +# prior versions are therefore excluded. +set_sw_property min_compatible_hw_version 7.1 + +# Initialize the driver in alt_sys_init() +set_sw_property auto_initialize true + +# Location in generated BSP that above sources will be copied into +set_sw_property bsp_subdirectory drivers + + +# Interrupt properties: +# This peripheral has an IRQ output but the driver doesn't currently +# have any interrupt service routine. To ensure that the BSP tools +# do not otherwise limit the BSP functionality for users of the +# Nios II enhanced interrupt port, these settings advertise +# compliance with both legacy and enhanced interrupt APIs, and to state +# that any driver ISR supports preemption. If an interrupt handler +# is added to this driver, these must be re-examined for validity. +set_sw_property isr_preemption_supported true +set_sw_property supported_interrupt_apis "legacy_interrupt_api enhanced_interrupt_api" + +# +# Source file listings... +# + +# C/C++ source files +add_sw_property c_source HAL/src/i2c_opencores.c + +# Include files +add_sw_property include_source HAL/inc/i2c_opencores.h +add_sw_property include_source inc/i2c_opencores_regs.h + +# This driver supports HAL & UCOSII BSP (OS) types +add_sw_property supported_bsp_type HAL +add_sw_property supported_bsp_type UCOSII + +# End of file diff --git a/ip/i2c_opencores/inc/i2c_opencores_regs.h b/ip/i2c_opencores/inc/i2c_opencores_regs.h new file mode 100644 index 0000000..17f79c3 --- /dev/null +++ b/ip/i2c_opencores/inc/i2c_opencores_regs.h @@ -0,0 +1,77 @@ + + +#ifndef __I2C_OPENCORES_REGS_H__ +#define __I2C_OPENCORES_REGS_H__ + +#include +/* prescal clock/(5*desired_SCL) */ +/* all registers are 8 bits wide but on 32 bit address boundaries.*/ +/* reg definitions take from i2c_specs.pdf in the docs folder */ + +#define IOADDR_I2C_OPENCORES_PRERLO(base) __IO_CALC_ADDRESS_NATIVE(base, 0) +#define IORD_I2C_OPENCORES_PRERLO(base) IORD(base, 0) +#define IOWR_I2C_OPENCORES_PRERLO(base, data) IOWR(base, 0, data) + + +#define IOADDR_I2C_OPENCORES_PRERHI(base) __IO_CALC_ADDRESS_NATIVE(base, 0) +#define IORD_I2C_OPENCORES_PRERHI(base) IORD(base, 1) +#define IOWR_I2C_OPENCORES_PRERHI(base, data) IOWR(base, 1, data) + + +#define IOADDR_I2C_OPENCORES_CTR(base) __IO_CALC_ADDRESS_NATIVE(base, 2) +#define IORD_I2C_OPENCORES_CTR(base) IORD(base, 2) +#define IOWR_I2C_OPENCORES_CTR(base, data) IOWR(base, 2, data) +/* bit definitions*/ +#define I2C_OPENCORES_CTR_EN_MSK (0x80) +#define I2C_OPENCORES_CTR_EN_OFST (7) +#define I2C_OPENCORES_CTR_IEN_MSK (0x40) +#define I2C_OPENCORES_CTR_IEN_OFST (6) + + +#define IOADDR_I2C_OPENCORES_TXR(base) __IO_CALC_ADDRESS_NATIVE(base, 3) +#define IOWR_I2C_OPENCORES_TXR(base, data) IOWR(base, 3, data) +/* bit definitions*/ +#define I2C_OPENCORES_TXR_RD_MSK (0x1) +#define I2C_OPENCORES_TXR_RD_OFST (0) +#define I2C_OPENCORES_TXR_WR_MSK (0x0) +#define I2C_OPENCORES_TXR_WR_OFST (0) + + +#define IOADDR_I2C_OPENCORES_RXR(base) __IO_CALC_ADDRESS_NATIVE(base, 3) +#define IORD_I2C_OPENCORES_RXR(base) IORD(base, 3) + + +#define IOADDR_I2C_OPENCORES_CR(base) __IO_CALC_ADDRESS_NATIVE(base, 4) +#define IOWR_I2C_OPENCORES_CR(base, data) IOWR(base, 4, data) +/* bit definitions*/ +#define I2C_OPENCORES_CR_STA_MSK (0x80) +#define I2C_OPENCORES_CR_STA_OFST (7) +#define I2C_OPENCORES_CR_STO_MSK (0x40) +#define I2C_OPENCORES_CR_STO_OFST (6) +#define I2C_OPENCORES_CR_RD_MSK (0x20) +#define I2C_OPENCORES_CR_RD_OFST (5) +#define I2C_OPENCORES_CR_WR_MSK (0x10) +#define I2C_OPENCORES_CR_WR_OFST (4) +#define I2C_OPENCORES_CR_NACK_MSK (0x8) +#define I2C_OPENCORES_CR_NACK_OFST (3) +#define I2C_OPENCORES_CR_SPIM_MSK (0x4) +#define I2C_OPENCORES_CR_SPIM_OFST (2) +#define I2C_OPENCORES_CR_IACK_MSK (0x1) +#define I2C_OPENCORES_CR_IACK_OFST (0) + + +#define IOADDR_I2C_OPENCORES_SR(base) __IO_CALC_ADDRESS_NATIVE(base, 4) +#define IORD_I2C_OPENCORES_SR(base) IORD(base, 4) +/* bit definitions*/ +#define I2C_OPENCORES_SR_RXNACK_MSK (0x80) +#define I2C_OPENCORES_SR_RXNACK_OFST (7) +#define I2C_OPENCORES_SR_BUSY_MSK (0x40) +#define I2C_OPENCORES_SR_BUSY_OFST (6) +#define I2C_OPENCORES_SR_AL_MSK (0x20) +#define I2C_OPENCORES_SR_AL_OFST (5) +#define I2C_OPENCORES_SR_TIP_MSK (0x2) +#define I2C_OPENCORES_SR_TIP_OFST (1) +#define I2C_OPENCORES_SR_IF_MSK (0x1) +#define I2C_OPENCORES_SR_IF_OFST (0) + +#endif /* __I2C_OPENCORES_REGS_H__ */ diff --git a/ip/i2c_opencores/timescale.v b/ip/i2c_opencores/timescale.v new file mode 100644 index 0000000..60d4ecb --- /dev/null +++ b/ip/i2c_opencores/timescale.v @@ -0,0 +1,2 @@ +`timescale 1ns / 10ps + diff --git a/ip/nios2_hw_crc/HAL/doc/crc_main.c b/ip/nios2_hw_crc/HAL/doc/crc_main.c new file mode 100644 index 0000000..d16548c --- /dev/null +++ b/ip/nios2_hw_crc/HAL/doc/crc_main.c @@ -0,0 +1,224 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/****************************************************************************** +* Author - JCJB * +* * +* This design uses the following CRC-32 implementations: * +* * +* --> Software - Uses modulo 2 division to perform the remainder calculation. * +* --> Optimized Software - Uses a lookup table of all possible division * +* values. The calculation operates on 8 bit data. * +* --> Custom Instruction - Uses a parallel hardware CRC circuit to calculate * +* the remainder. The calculation operates on 8, * +* 16, 24, or 32 bit data. * +* * +* The software implementations can be changed to CRC-16 or CRC-CCITT however * +* the custom instruction must be modified as well to support the same * +* standard. Simply use the values defined in crc.h to change the standard * +* used (using the same values in the hardware parameterization) or define * +* your own standard. * +*******************************************************************************/ + +#include "system.h" +#include "stdio.h" +#include "crc.h" +#include "ci_crc.h" +#include "sys/alt_timestamp.h" +#include "stdlib.h" + + +/* Modify these values to adjust the test being performed */ +#define NUMBER_OF_BUFFERS 32 +#define BUFFER_SIZE 256 /* in bytes */ + +/* Change the name of memory device according to what you are using + * e.g.: DDR_SDRAM_0 ##_SPAN + * SSRAM_0 ##_SPAN + */ +#define MEMORY_DEVICE_SIZE 32768 + + +/* Make sure there is room left for Nios II text, rodata, rwdata, stack, + * and heap. This software and the buffer space must fit within the + * size of memory device. A total of 1.5 MBytes is reserved. If BUFFER_SIZE + * is a multiple of four then exactly 256kB will be left, otherwise is + * amount will be less since the column dimension needs some padding to + * stay 32 bit aligned + */ +#if ((BUFFER_SIZE * NUMBER_OF_BUFFERS) >= MEMORY_DEVICE_SIZE - 10000) + #error Your buffer space has exceeded the maximum allowable space. Please\ + reduce the buffer space so that there is enough room to hold Nios II\ + code. +#endif + + +/* This will line up the data onto a 32 bit (or greater) boundary. A 2d array + * is being used here for simplicity. The first dimension represents a byte + * of data and the second dimension represents an individual buffer + */ +#if ((BUFFER_SIZE & 0x3) == 0) + unsigned char data_buffer_region[NUMBER_OF_BUFFERS][BUFFER_SIZE] __attribute__ ((aligned(4))); +#else /* need to allocate extra bytes so that all buffers start on a 32 bit + boundaries by rounding up the column dimension to the next power of 4 + */ + unsigned char data_buffer_region[NUMBER_OF_BUFFERS][BUFFER_SIZE + 4 - (BUFFER_SIZE&0x3)] __attribute__ ((aligned(4))); +#endif + + + + + +int main() +{ + unsigned long buffer_counter, data_counter; + unsigned long sw_slow_results[NUMBER_OF_BUFFERS]; + unsigned long sw_fast_results[NUMBER_OF_BUFFERS]; + unsigned long ci_results[NUMBER_OF_BUFFERS]; + unsigned char random_data = 0x5A; + //unsigned long sw_slow_timeA, sw_slow_timeB; + // unsigned long sw_fast_timeA, sw_fast_timeB; + // unsigned long ci_timeA, ci_timeB; + + alt_u32 sw_slow_timeA, sw_slow_timeB; + alt_u32 sw_fast_timeA, sw_fast_timeB; + alt_u32 ci_timeA, ci_timeB; + + + printf("+-----------------------------------------------------------+\n"); + printf("| Comparison between software and custom instruction CRC32 |\n"); + printf("+-----------------------------------------------------------+\n\n\n"); + + printf("System specification\n"); + printf("--------------------\n"); + + printf("System clock speed = %lu MHz\n", (unsigned long)ALT_CPU_FREQ /(unsigned long)1000000); + printf("Number of buffer locations = %d\n", NUMBER_OF_BUFFERS); + printf("Size of each buffer = %d bytes\n\n\n", BUFFER_SIZE); + + + /* Initializing the data buffers */ + printf("Initializing all of the buffers with pseudo-random data\n"); + printf("-------------------------------------------------------\n"); + for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++) + { + for(data_counter = 0; data_counter < BUFFER_SIZE; data_counter++) + { + data_buffer_region[buffer_counter][data_counter] = random_data; + random_data = (random_data >> 4) + (random_data << 4) + (data_counter & 0xFF); + } + } + printf("Initialization completed\n\n\n"); + + + if(alt_timestamp_start() < 0) // starts the timestamp timer + { + printf("Please add the high resolution timer to the timestamp timer setting in the syslib properties page.\n"); + exit(1); + } + + + /* Slow software CRC based on a modulo 2 division implementation */ + printf("Running the software CRC\n"); + printf("------------------------\n"); + sw_slow_timeA = alt_timestamp(); + + for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++) + { + sw_slow_results[buffer_counter] = crcSlow(data_buffer_region[buffer_counter], BUFFER_SIZE); + } + sw_slow_timeB = alt_timestamp(); + + printf("Completed\n\n\n"); + + + /* Fast software CRC based on a lookup table implementation */ + crcInit(); + printf("Running the optimized software CRC\n"); + printf("----------------------------------\n"); + sw_fast_timeA = alt_timestamp(); + for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++) + { + sw_fast_results[buffer_counter] = crcFast(data_buffer_region[buffer_counter], BUFFER_SIZE); + } + sw_fast_timeB = alt_timestamp(); + printf("Completed\n\n\n"); + + + /* Custom instruction CRC */ + printf("Running the custom instruction CRC\n"); + printf("----------------------------------\n"); + ci_timeA = alt_timestamp(); + for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++) + { + ci_results[buffer_counter] = crcCI(data_buffer_region[buffer_counter], BUFFER_SIZE); + } + ci_timeB = alt_timestamp(); + printf("Completed\n\n\n"); + + /* Validation of results */ + printf("Validating the CRC results from all implementations\n"); + printf("----------------------------------------------------\n"); + for(buffer_counter = 0; buffer_counter < NUMBER_OF_BUFFERS; buffer_counter++) + { + /* Test every combination of results to make sure they are consistant */ + if((sw_slow_results[buffer_counter] != ci_results[buffer_counter]) | + (sw_fast_results[buffer_counter] != ci_results[buffer_counter])) + { + printf("FAILURE! Software CRC = 0x%lx, Optimized Software CRC = 0x%lx, Custom Instruction CRC = 0x%lx,\n", + sw_slow_results[buffer_counter], sw_fast_results[buffer_counter], ci_results[buffer_counter]); + exit(1); + } + } + printf("All CRC implementations produced the same results\n\n\n"); + + + // Report processing times + printf("Processing time for each implementation\n"); + printf("---------------------------------------\n"); + printf("Software CRC = %.2lu ms\n", 1000*((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)alt_timestamp_freq())); + printf("Optimized software CRC = %.2lu ms\n", 1000*((unsigned long)(sw_fast_timeB-sw_fast_timeA))/((unsigned long)alt_timestamp_freq())); + printf("Custom instruction CRC = %.2lu ms\n\n\n", 1000*((unsigned long)(ci_timeB-ci_timeA))/((unsigned long)alt_timestamp_freq())); + + printf("Processing throughput for each implementation\n"); // throughput = total bits / (time(s) * 1000000) + printf("---------------------------------------------\n"); + printf("Software CRC = %.2lu Mbps\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(sw_slow_timeB-sw_slow_timeA)/((unsigned long)alt_timestamp_freq()))); + printf("Optimized software CRC = %.2lu Mbps\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(sw_fast_timeB-sw_fast_timeA)/((unsigned long)alt_timestamp_freq()))); + printf("Custom instruction CRC = %.2lu Mbps\n\n\n", (8 * NUMBER_OF_BUFFERS * BUFFER_SIZE)/(1000000*(unsigned long)(ci_timeB-ci_timeA)/((unsigned long)alt_timestamp_freq()))); + + printf("Speedup ratio\n"); + printf("-------------\n"); + printf("Custom instruction CRC vs software CRC = %lu\n", ((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)(ci_timeB-ci_timeA))); + printf("Custom instruction CRC vs optimized software CRC = %lu\n", ((unsigned long)(sw_fast_timeB-sw_fast_timeA))/((unsigned long)(ci_timeB-ci_timeA))); + printf("Optimized software CRC vs software CRC= %lu\n", ((unsigned long)(sw_slow_timeB-sw_slow_timeA))/((unsigned long)(sw_fast_timeB-sw_fast_timeA))); + return 0; +} diff --git a/ip/nios2_hw_crc/HAL/inc/ci_crc.h b/ip/nios2_hw_crc/HAL/inc/ci_crc.h new file mode 100644 index 0000000..ba4d983 --- /dev/null +++ b/ip/nios2_hw_crc/HAL/inc/ci_crc.h @@ -0,0 +1,38 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +#ifndef _CRCCI_H_ +#define _CRCCI_H_ + +unsigned long crcCI(unsigned char * input_data, unsigned long input_data_length, int do_initialize); + +#endif //_CRCCI_H_ diff --git a/ip/nios2_hw_crc/HAL/inc/crc.h b/ip/nios2_hw_crc/HAL/inc/crc.h new file mode 100644 index 0000000..4db516e --- /dev/null +++ b/ip/nios2_hw_crc/HAL/inc/crc.h @@ -0,0 +1,109 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/********************************************************************** + * + * Filename: crc.h + * + * Description: A header file describing the various CRC standards. + * + * Notes: + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#ifndef _crc_h +#define _crc_h + + +#define FALSE 0 +#define TRUE !FALSE + +/* + * Select the CRC standard from the list that follows. + */ +#define CRC32 + + +#if defined(CRC_CCITT) + +typedef unsigned short crc; + +#define CRC_NAME "CRC-CCITT" +#define POLYNOMIAL 0x1021 +#define INITIAL_REMAINDER 0xFFFF +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA FALSE +#define REFLECT_REMAINDER FALSE +#define CHECK_VALUE 0x29B1 + +#elif defined(CRC16) + +typedef unsigned short crc; + +#define CRC_NAME "CRC-16" +#define POLYNOMIAL 0x8005 +#define INITIAL_REMAINDER 0x0000 +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xBB3D + +#elif defined(CRC32) + +typedef unsigned long crc; + +#define CRC_NAME "CRC-32" +#define POLYNOMIAL 0x04C11DB7 +#define INITIAL_REMAINDER 0xFFFFFFFF +#define FINAL_XOR_VALUE 0xFFFFFFFF +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xCBF43926 + +#else + +#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd." + +#endif + + +void crcInit(void); +crc crcSlow(unsigned char const message[], int nBytes); +crc crcFast(unsigned char const message[], int nBytes); + + +#endif /* _crc_h */ diff --git a/ip/nios2_hw_crc/HAL/src/ci_crc.c b/ip/nios2_hw_crc/HAL/src/ci_crc.c new file mode 100644 index 0000000..7f9b0f0 --- /dev/null +++ b/ip/nios2_hw_crc/HAL/src/ci_crc.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/********************************************************************** + * + * Filename: ci_crc.c + * + * Description: Custom instruction implementations of the CRC. + * + * Notes: A macro is defined that is used to access the CRC custom + * instruction. + *********************************************************************/ + +#include "system.h" + +/*The n values and their corresponding operation are as follow: + * n = 0, Initialize the custom instruction to the initial remainder value + * n = 1, Write 8 bits data to custom instruction + * n = 2, Write 16 bits data to custom instruction + * n = 3, Write 32 bits data to custom instruction + * n = 4, Read 32 bits data from the custom instruction + * n = 5, Read 64 bits data from the custom instruction + * n = 6, Read 96 bits data from the custom instruction + * n = 7, Read 128 bits data from the custom instruction*/ +#define CRC_CI_MACRO(n, A) __builtin_custom_ini(ALT_CI_NIOS2_HW_CRC32_0_N + (n & 0x7), (A)) + +unsigned long crcCI(unsigned char * input_data, unsigned long input_data_length, int do_initialize) +{ + unsigned long index; + /* copy of the data buffer pointer so that it can advance by different widths */ + void * input_data_copy = (void *)input_data; + + /* The custom instruction CRC will initialize to the inital remainder value */ + if (do_initialize) + CRC_CI_MACRO(0,0); + + /* Write 32 bit data to the custom instruction. If the buffer does not end + * on a 32 bit boundary then the remaining data will be sent to the custom + * instruction in the 'if' statement below. + */ + for(index = 0; index < (input_data_length & 0xFFFFFFFC); index+=4) + { + CRC_CI_MACRO(3, *(unsigned long *)input_data_copy); + input_data_copy += 4; /* void pointer, must move by 4 for each word */ + } + + /* Write the remainder of the buffer if it does not end on a word boundary */ + if((input_data_length & 0x3) == 0x3) /* 3 bytes left */ + { + CRC_CI_MACRO(2, *(unsigned short *)input_data_copy); + input_data_copy += 2; + CRC_CI_MACRO(1, *(unsigned char *)input_data_copy); + } + else if((input_data_length & 0x3) == 0x2) /* 2 bytes left */ + { + CRC_CI_MACRO(2, *(unsigned short *)input_data_copy); + } + else if((input_data_length & 0x3) == 0x1) /* 1 byte left */ + { + CRC_CI_MACRO(1, *(unsigned char *)input_data_copy); + } + + /* There are 4 registers in the CRC custom instruction. Since + * this example uses CRC-32 only the first register must be read + * in order to receive the full result. + */ + return CRC_CI_MACRO(4, 0); +} diff --git a/ip/nios2_hw_crc/HAL/src/crc.c b/ip/nios2_hw_crc/HAL/src/crc.c new file mode 100644 index 0000000..f00568d --- /dev/null +++ b/ip/nios2_hw_crc/HAL/src/crc.c @@ -0,0 +1,265 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/********************************************************************** + * + * Filename: crc.c + * + * Description: Slow and fast implementations of the CRC standards. + * + * Notes: The parameters for each supported CRC standard are + * defined in the header file crc.h. The implementations + * here should stand up to further additions to that list. + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#include "crc.h" + + +/* + * Derive parameters from the standard-specific parameters in crc.h. + */ +#define WIDTH (8 * sizeof(crc)) +#define TOPBIT (1 << (WIDTH - 1)) + +#if (REFLECT_DATA == TRUE) +#undef REFLECT_DATA +#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8)) +#else +#undef REFLECT_DATA +#define REFLECT_DATA(X) (X) +#endif + +#if (REFLECT_REMAINDER == TRUE) +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH)) +#else +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) (X) +#endif + + +/********************************************************************* + * + * Function: reflect() + * + * Description: Reorder the bits of a binary sequence, by reflecting + * them about the middle position. + * + * Notes: No checking is done that nBits <= 32. + * + * Returns: The reflection of the original data. + * + *********************************************************************/ +static unsigned long +reflect(unsigned long data, unsigned char nBits) +{ + unsigned long reflection = 0x00000000; + unsigned char bit; + + /* + * Reflect the data about the center bit. + */ + for (bit = 0; bit < nBits; ++bit) + { + /* + * If the LSB bit is set, set the reflection of it. + */ + if (data & 0x01) + { + reflection |= (1 << ((nBits - 1) - bit)); + } + + data = (data >> 1); + } + + return (reflection); + +} /* reflect() */ + + +/********************************************************************* + * + * Function: crcSlow() + * + * Description: Compute the CRC of a given message. + * + * Notes: + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcSlow(unsigned char const message[], int nBytes) +{ + crc remainder = INITIAL_REMAINDER; + int byte; + unsigned char bit; + + + /* + * Perform modulo-2 division, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) + { + /* + * Bring the next byte into the remainder. + */ + remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8)); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) + { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) + { + remainder = (remainder << 1) ^ POLYNOMIAL; + } + else + { + remainder = (remainder << 1); + } + } + } + + /* + * The final remainder is the CRC result. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcSlow() */ + + +crc crcTable[256]; + + +/********************************************************************* + * + * Function: crcInit() + * + * Description: Populate the partial CRC lookup table. + * + * Notes: This function must be rerun any time the CRC standard + * is changed. If desired, it can be run "offline" and + * the table results stored in an embedded system's ROM. + * + * Returns: None defined. + * + *********************************************************************/ +void +crcInit(void) +{ + crc remainder; + int dividend; + unsigned char bit; + + + /* + * Compute the remainder of each possible dividend. + */ + for (dividend = 0; dividend < 256; ++dividend) + { + /* + * Start with the dividend followed by zeros. + */ + remainder = dividend << (WIDTH - 8); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) + { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) + { + remainder = (remainder << 1) ^ POLYNOMIAL; + } + else + { + remainder = (remainder << 1); + } + } + + /* + * Store the result into the table. + */ + crcTable[dividend] = remainder; + } + +} /* crcInit() */ + + +/********************************************************************* + * + * Function: crcFast() + * + * Description: Compute the CRC of a given message. + * + * Notes: crcInit() must be called first. + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcFast(unsigned char const message[], int nBytes) +{ + crc remainder = INITIAL_REMAINDER; + unsigned char data; + int byte; + + + /* + * Divide the message by the polynomial, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) + { + data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)); + remainder = crcTable[data] ^ (remainder << 8); + } + + /* + * The final remainder is the CRC. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcFast() */ diff --git a/ip/nios2_hw_crc/hdl/CRC_Component.v b/ip/nios2_hw_crc/hdl/CRC_Component.v new file mode 100644 index 0000000..5c67836 --- /dev/null +++ b/ip/nios2_hw_crc/hdl/CRC_Component.v @@ -0,0 +1,314 @@ +/* + Legal Notice: (C)2006 Altera Corporation. All rights reserved. Your + use of Altera Corporation's design tools, logic functions and other + software and tools, and its AMPP partner logic functions, and any + output files any of the foregoing (including device programming or + simulation files), and any associated documentation or information are + expressly subject to the terms and conditions of the Altera Program + License Subscription Agreement or other applicable license agreement, + including, without limitation, that your use is for the sole purpose + of programming logic devices manufactured by Altera and sold by Altera + or its authorized distributors. Please refer to the applicable + agreement for further details. +*/ + +/* + This component supports 8, 16, 24, and 32 bit little endian data + and any CRC standard between 1 to 128 bits. Through parameterization + you can change the CRC standard which will take effect after you + regenerate your system in SOPC Builder. + + Register Map: + 000 -> reset the CRC peripheral to the inital value (data and byte enables ignored) + 001 -> data write between 1-32 bits + 010 -> reserved + 011 -> reserved + 100 -> read bits 1-32 of the crc result + 101 -> read bits 33-64 of the crc result (where applicable) + 110 -> read bits 65-96 of the crc result (where applicable) + 111 -> read bits 97-128 of the crc result (where applicable) + + Write latency = 0 + Read latency = 1 + + Note: This component uses four blocks of eight bits of data in cascade. + To improve the timing of logic you can create seperate cascades + for 8, 16, 24, and 32 bit data which will allow for smaller area + and a shorter combinational depth. Since CRC logic consumes power + even when not in use you can also add a logic disable feature using + the chipselect signal. Even though the registered CRC value is + held constant when the circuit is not in use the input data will + change during this time and cause the CRC cascade logic to react. +*/ + + +module CRC_Component (clk, + reset, + address, + writedata, + byteenable, + write, + read, + chipselect, + readdata); + +/* + Using these parameters you can create any CRC ranging from one bit (parity checker) + up to 128 bits. The following list describes the function of each parameter: + + crc_width: + The width of the registered CRC result, this value is typically apart of + the name of the standard (CRC32 is 32 bits wide). Adjusting this value + will impact the logic resource usage. + + polynomial_initial: + The initial value set for the CRC result register. By writing any data to address 0 + this value will be stored in the result register thereby clearing any previously existing + value. This value must be the same width as 'crc_width' + + polynomial: + This is the divisor value used on the input data. Typically shown in polynomial format + the value symbolizes the placement of xor operation on the input data. In synthesis, the + polynomial bits that are '1' will create a not gate, whereas the bits that are '0' will + simply create a wire. Even with 32 stages of these operations cascaded, the simple logic + will not become a significant factor on logic utilization or fmax. This value must be the + same width as 'crc_width' + + reflected_input: + Some CRC standards require that all the input bits be reflected around the center point. + This option is enabled with '1' and disabled with '0'. Typically this option is enabled + or disabled with 'reflected_output'. + + reflected_output: + Some CRC standards require that all the output bits be reflected around the center point. + This operation occurs before the final optional xor output step. This option is enabled + with '1' and disabled with '0'. Typically this option is enabled or disabled with + 'reflected_input' (to undo the input reversal typically). + + xor_output: + This is the value used to bitwise xor the CRC result. Most standards use either all zeros + or all ones for this value. When zeros are used the CRC result is passed directly and when + ones are used the CRC result is inverted. Since it's no mandatory that this value be all + ones or zeros, this operation occurs before the output reflection when applicable. +*/ + + parameter crc_width = 32; + parameter polynomial_inital = 32'hFFFFFFFF; + parameter polynomial = 32'h04C11DB7; + parameter reflected_input = 1; + parameter reflected_output = 1; + parameter xor_output = 32'hFFFFFFFF; + + + input clk; + input reset; + input [2:0] address; + input [31:0] writedata; + input [3:0] byteenable; + input write; + input read; + input chipselect; + output [31:0] readdata; + + reg [crc_width-1:0] crc_value; + wire [crc_width-1:0] poly = polynomial; + wire [crc_width-1:0] cascade [3:0]; + wire [7:0] block0_data, block1_data, block2_data, block3_data; + wire [crc_width-1:0] result, result_xored; + wire [31:0] mux_result; + reg [31:0] readdata; + + + /* + Some standards like CRC16 and CRC32 require this bitreversal for serial + devices like ethernet, uarts, usb, etc... + */ + genvar index; + generate if (reflected_input == 1) + begin + for(index = 0; index < 8; index = index + 1) + begin: input_reflection + assign block0_data[index] = writedata[7-index]; + assign block1_data[index] = writedata[15-index]; + assign block2_data[index] = writedata[23-index]; + assign block3_data[index] = writedata[31-index]; + end + end + else + begin + assign block0_data = writedata[7:0]; + assign block1_data = writedata[15:8]; + assign block2_data = writedata[23:16]; + assign block3_data = writedata[31:24]; + end + endgenerate + + + /* + Control for the registered events. It assumes that either 8, 16, 24, or 32 + bit data is being written using byte enables. It is important that the data + be in little endian format and no gaps of byte enables be present (like + 1011 or 1101 for example) + */ + always @ (posedge clk or posedge reset) + begin + if(reset == 1) + begin + crc_value <= 0; + end + else + begin + if(write && chipselect && (address == 3'b000)) + begin + crc_value <= polynomial_inital; // reset the crc to the initial value + end + else if(write && chipselect && (address == 3'b001)) + begin + if(byteenable == 4'b0001) // 8 bit data input + begin + crc_value <= cascade[0]; + end + else if(byteenable == 4'b0011) // 16 bit data input + begin + crc_value <= cascade[1]; + end + else if(byteenable == 4'b0111) // 24 bit data input + begin + crc_value <= cascade[2]; + end + else if(byteenable == 4'b1111) // 32 bit data input + begin + crc_value <= cascade[3]; + end + end + end + end + + + /* four stages of cascade blocks (each block is crc_width x 8 bits) */ + XOR_Shift_Block cascade_block0(.block_input(crc_value), .poly(poly), .data_input(block0_data), .block_output(cascade[0])); + defparam cascade_block0.crc_width = crc_width; + XOR_Shift_Block cascade_block1(.block_input(cascade[0]), .poly(poly), .data_input(block1_data), .block_output(cascade[1])); + defparam cascade_block1.crc_width = crc_width; + XOR_Shift_Block cascade_block2(.block_input(cascade[1]), .poly(poly), .data_input(block2_data), .block_output(cascade[2])); + defparam cascade_block2.crc_width = crc_width; + XOR_Shift_Block cascade_block3(.block_input(cascade[2]), .poly(poly), .data_input(block3_data), .block_output(cascade[3])); + defparam cascade_block3.crc_width = crc_width; + + + + /* + Some standards like CRC16 and CRC32 require this bitreversal. + This is to better support serial devices like uarts, ethernet, usb, etc...) + */ + generate if (reflected_output == 1) + begin + for(index = 0; index < crc_width; index = index + 1) + begin: output_reflection32 + assign result[index] = crc_value[(crc_width-1)-index]; + end + end + else + begin + assign result = crc_value; + end + endgenerate + + + /* This final xor operation occurs after the bit swap */ + assign result_xored = result ^ xor_output; + + + /* Generates the appropriate MUX logic depending on the CRC width */ + generate if((crc_width > 32) && (crc_width < 65)) + begin + assign mux_result = (address == 3'b100)? result_xored[31:0] : result_xored[crc_width-1:32]; + end + else if((crc_width > 64) && (crc_width < 97)) + begin + assign mux_result = (address == 3'b100)? result_xored[31:0] : + ((address == 3'b101)? result_xored[63:32] : result_xored[crc_width-1:64]); + end + else if((crc_width > 96) && (crc_width < 129)) + begin + assign mux_result = (address == 3'b100)? result_xored[31:0] : + ((address == 3'b101)? result_xored[63:32] : + ((address == 3'b110)? result_xored[95:64] : result_xored[crc_width-1:96])); + end + else + begin + assign mux_result = result_xored; + end + endgenerate + + + /* Registering the return path of the CRC data (32 bits of it) */ + always @ (posedge clk or posedge reset) + begin + if(reset == 1) + begin + readdata <= 0; + end + else if((read == 1) && (chipselect == 1)) + begin + readdata <= mux_result; + end + end + +endmodule + + + +/* a single cascade block of width: crc_width and a length of eight input bits */ +module XOR_Shift_Block(block_input, + poly, + data_input, + block_output); + parameter crc_width = 32; + + input [(crc_width-1):0] block_input; + input [(crc_width-1):0] poly; + input [7:0] data_input; + output [(crc_width-1):0] block_output; + + wire [(crc_width-1):0] cascade [7:0]; + + XOR_Shift bit_0(.stage_input(block_input), .poly(poly), .new_bit(data_input[7]), .stage_output(cascade[0])); + defparam bit_0.crc_width = crc_width; + XOR_Shift bit_1(.stage_input(cascade[0]), .poly(poly), .new_bit(data_input[6]), .stage_output(cascade[1])); + defparam bit_1.crc_width = crc_width; + XOR_Shift bit_2(.stage_input(cascade[1]), .poly(poly), .new_bit(data_input[5]), .stage_output(cascade[2])); + defparam bit_2.crc_width = crc_width; + XOR_Shift bit_3(.stage_input(cascade[2]), .poly(poly), .new_bit(data_input[4]), .stage_output(cascade[3])); + defparam bit_3.crc_width = crc_width; + XOR_Shift bit_4(.stage_input(cascade[3]), .poly(poly), .new_bit(data_input[3]), .stage_output(cascade[4])); + defparam bit_4.crc_width = crc_width; + XOR_Shift bit_5(.stage_input(cascade[4]), .poly(poly), .new_bit(data_input[2]), .stage_output(cascade[5])); + defparam bit_5.crc_width = crc_width; + XOR_Shift bit_6(.stage_input(cascade[5]), .poly(poly), .new_bit(data_input[1]), .stage_output(cascade[6])); + defparam bit_6.crc_width = crc_width; + XOR_Shift bit_7(.stage_input(cascade[6]), .poly(poly), .new_bit(data_input[0]), .stage_output(cascade[7])); + defparam bit_7.crc_width = crc_width; + + assign block_output = cascade[7]; + +endmodule + + +/* performs the 'new_bit' stuffing, shifting, and XOR operations for a single input bit */ +module XOR_Shift (stage_input, + poly, + new_bit, + stage_output); + + parameter crc_width = 32; + + input [crc_width-1:0] stage_input; + input [crc_width-1:0] poly; + input new_bit; + output [crc_width-1:0] stage_output; + + assign stage_output[0] = new_bit ^ stage_input[crc_width-1]; + assign stage_output[crc_width-1:1] = stage_input[crc_width-2:0] ^ ({crc_width-1{stage_output[0]}} & poly[crc_width-1:1]); + +endmodule diff --git a/ip/nios2_hw_crc/hdl/CRC_Custom_Instruction.v b/ip/nios2_hw_crc/hdl/CRC_Custom_Instruction.v new file mode 100644 index 0000000..f24f7bb --- /dev/null +++ b/ip/nios2_hw_crc/hdl/CRC_Custom_Instruction.v @@ -0,0 +1,101 @@ +/* + Legal Notice: (C)2006 Altera Corporation. All rights reserved. Your + use of Altera Corporation's design tools, logic functions and other + software and tools, and its AMPP partner logic functions, and any + output files any of the foregoing (including device programming or + simulation files), and any associated documentation or information are + expressly subject to the terms and conditions of the Altera Program + License Subscription Agreement or other applicable license agreement, + including, without limitation, that your use is for the sole purpose + of programming logic devices manufactured by Altera and sold by Altera + or its authorized distributors. Please refer to the applicable + agreement for further details. +*/ + +/* + This thin wrapper re-uses the CRC Avalon component as a Nios II + custom instruction. The n port of custom instruction is used as + control to the CRC Avalon component. Below are the values of n and + the corresponding operations perform by the custom instruction: + n = 0, Initialize the custom instruction to the initial remainder value + n = 1, Write 8 bits data to custom instruction + n = 2, Write 16 bits data to custom instruction + n = 3, Write 32 bits data to custom instruction + n = 4, Read 32 bits data from the custom instruction + n = 5, Read 64 bits data from the custom instruction + n = 6, Read 96 bits data from the custom instruction + n = 7, Read 128 bits data from the custom instruction +*/ + + + +module CRC_Custom_Instruction(clk, + reset, + dataa, + n, + clk_en, + start, + done, + result); + /* + See the Avalon CRC component for details on the meaning of each + parameter listed below. + */ + parameter crc_width = 32; + parameter polynomial_inital = 32'hFFFFFFFF; + parameter polynomial = 32'h04C11DB7; + parameter reflected_input = 1; + parameter reflected_output = 1; + parameter xor_output = 32'hFFFFFFFF; + + input clk; + input reset; + input [31:0] dataa; + input [2:0] n; + input clk_en; + input start; + output done; + output [31:0] result; + + wire [2:0] address; + wire [3:0] byteenable; + wire write; + wire read; + reg done_delay; + + assign write = (n<4); + assign read = (n>3); + assign byteenable = (n==1)?4'b0001 : (n==2)?4'b0011 : (n==3)?4'b1111 : 4'b0000; + assign address = (n==0)?3'b000 : ((n==1)|(n==2)|(n==3))?3'b001 : (n==4)?3'b100 : (n==5)?3'b101 : (n==6)?3'b110 : 3'b111; + assign done = (n>3)? done_delay : start; + + always @ (posedge clk or posedge reset) + begin + if (reset) + done_delay <= 0; + else + done_delay <= start; + end + + /* + Instantiating the Avalon CRC component and wiring it to be + custom instruction compilant + */ + CRC_Component wrapper_wiring(.clk(clk), + .reset(reset), + .address(address), + .writedata(dataa), + .byteenable(byteenable), + .write(write & start), + .read(read), + .chipselect(clk_en), + .readdata(result)); + + defparam wrapper_wiring.crc_width = crc_width; + defparam wrapper_wiring.polynomial_inital = polynomial_inital; + defparam wrapper_wiring.polynomial = polynomial; + defparam wrapper_wiring.reflected_input = reflected_input; + defparam wrapper_wiring.reflected_output = reflected_output; + defparam wrapper_wiring.xor_output = xor_output; + +endmodule diff --git a/ip/nios2_hw_crc/nios2_hw_crc32_hw.tcl b/ip/nios2_hw_crc/nios2_hw_crc32_hw.tcl new file mode 100644 index 0000000..ecc57d0 --- /dev/null +++ b/ip/nios2_hw_crc/nios2_hw_crc32_hw.tcl @@ -0,0 +1,116 @@ +# TCL File Generated by Component Editor 15.1 +# Tue Dec 22 18:46:40 EET 2015 +# DO NOT MODIFY + + +# +# nios2_hw_crc32 "nios2_hw_crc32" v1.0 +# 2015.12.22.18:46:40 +# +# + +# +# request TCL package from ACDS 15.1 +# +package require -exact qsys 15.1 + + +# +# module nios2_hw_crc32 +# +set_module_property DESCRIPTION "" +set_module_property NAME nios2_hw_crc32 +set_module_property VERSION 1.0 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property GROUP "Custom Instruction Modules" +set_module_property AUTHOR "" +set_module_property DISPLAY_NAME nios2_hw_crc32 +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE true +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false + + +# +# file sets +# +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" +set_fileset_property QUARTUS_SYNTH TOP_LEVEL CRC_Custom_Instruction +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false +add_fileset_file CRC_Component.v VERILOG PATH hdl/CRC_Component.v +add_fileset_file CRC_Custom_Instruction.v VERILOG PATH hdl/CRC_Custom_Instruction.v TOP_LEVEL_FILE + + +# +# parameters +# +add_parameter crc_width INTEGER 32 +set_parameter_property crc_width DEFAULT_VALUE 32 +set_parameter_property crc_width DISPLAY_NAME crc_width +set_parameter_property crc_width TYPE INTEGER +set_parameter_property crc_width UNITS None +set_parameter_property crc_width HDL_PARAMETER true +add_parameter polynomial_inital STD_LOGIC_VECTOR 4294967295 +set_parameter_property polynomial_inital DEFAULT_VALUE 4294967295 +set_parameter_property polynomial_inital DISPLAY_NAME polynomial_inital +set_parameter_property polynomial_inital TYPE STD_LOGIC_VECTOR +set_parameter_property polynomial_inital UNITS None +set_parameter_property polynomial_inital ALLOWED_RANGES 0:17179869183 +set_parameter_property polynomial_inital HDL_PARAMETER true +add_parameter polynomial STD_LOGIC_VECTOR 79764919 +set_parameter_property polynomial DEFAULT_VALUE 79764919 +set_parameter_property polynomial DISPLAY_NAME polynomial +set_parameter_property polynomial TYPE STD_LOGIC_VECTOR +set_parameter_property polynomial UNITS None +set_parameter_property polynomial ALLOWED_RANGES 0:17179869183 +set_parameter_property polynomial HDL_PARAMETER true +add_parameter reflected_input INTEGER 1 +set_parameter_property reflected_input DEFAULT_VALUE 1 +set_parameter_property reflected_input DISPLAY_NAME reflected_input +set_parameter_property reflected_input TYPE INTEGER +set_parameter_property reflected_input UNITS None +set_parameter_property reflected_input HDL_PARAMETER true +add_parameter reflected_output INTEGER 1 +set_parameter_property reflected_output DEFAULT_VALUE 1 +set_parameter_property reflected_output DISPLAY_NAME reflected_output +set_parameter_property reflected_output TYPE INTEGER +set_parameter_property reflected_output UNITS None +set_parameter_property reflected_output HDL_PARAMETER true +add_parameter xor_output STD_LOGIC_VECTOR 4294967295 +set_parameter_property xor_output DEFAULT_VALUE 4294967295 +set_parameter_property xor_output DISPLAY_NAME xor_output +set_parameter_property xor_output TYPE STD_LOGIC_VECTOR +set_parameter_property xor_output UNITS None +set_parameter_property xor_output ALLOWED_RANGES 0:17179869183 +set_parameter_property xor_output HDL_PARAMETER true + + +# +# display items +# + + +# +# connection point nios_custom_instruction_slave +# +add_interface nios_custom_instruction_slave nios_custom_instruction end +set_interface_property nios_custom_instruction_slave clockCycle 0 +set_interface_property nios_custom_instruction_slave operands 1 +set_interface_property nios_custom_instruction_slave ENABLED true +set_interface_property nios_custom_instruction_slave EXPORT_OF "" +set_interface_property nios_custom_instruction_slave PORT_NAME_MAP "" +set_interface_property nios_custom_instruction_slave CMSIS_SVD_VARIABLES "" +set_interface_property nios_custom_instruction_slave SVD_ADDRESS_GROUP "" + +add_interface_port nios_custom_instruction_slave clk clk Input 1 +add_interface_port nios_custom_instruction_slave clk_en clk_en Input 1 +add_interface_port nios_custom_instruction_slave dataa dataa Input 32 +add_interface_port nios_custom_instruction_slave done done Output 1 +add_interface_port nios_custom_instruction_slave n n Input 3 +add_interface_port nios_custom_instruction_slave reset reset Input 1 +add_interface_port nios_custom_instruction_slave result result Output 32 +add_interface_port nios_custom_instruction_slave start start Input 1 + diff --git a/ip/nios2_hw_crc/nios2_hw_crc32_sw.tcl b/ip/nios2_hw_crc/nios2_hw_crc32_sw.tcl new file mode 100644 index 0000000..ce0d0e4 --- /dev/null +++ b/ip/nios2_hw_crc/nios2_hw_crc32_sw.tcl @@ -0,0 +1,58 @@ +# (C) 2001-2015 Altera Corporation. All rights reserved. +# Your use of Altera Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License Subscription +# Agreement, Altera MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# TCL File Generated by Altera University Program +# DO NOT MODIFY + +set aup_version 15.1 + +# Create a new driver - this name must be different than the +# hardware component name +create_driver nios2_hw_crc32_driver + +# Associate it with some hardware +set_sw_property hw_class_name nios2_hw_crc32 + +# The version of this driver +set_sw_property version $aup_version + +# This driver is proclaimed to be compatible with 'component' +# as old as version "1.0". The component hardware version is set in the +# _hw.tcl file - If the hardware component version number is not equal +# or greater than the min_compatable_hw_version number, the driver +# source files will not be copied over to the BSP driver directory +set_sw_property min_compatible_hw_version 1.0 + +# Initialize the driver in alt_sys_init() +set_sw_property auto_initialize false + +# Location in generated BSP that sources will be copied into +set_sw_property bsp_subdirectory drivers + +# +# Source file listings... +# + +# C/C++ source files +add_sw_property c_source HAL/src/ci_crc.c +add_sw_property c_source HAL/src/crc.c + +# Include files +add_sw_property include_source HAL/inc/ci_crc.h +add_sw_property include_source HAL/inc/crc.h + +# This driver supports HAL type +add_sw_property supported_bsp_type HAL + +# End of file + diff --git a/ossc.qpf b/ossc.qpf new file mode 100644 index 0000000..5dfcec8 --- /dev/null +++ b/ossc.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 17:27:03 May 17, 2014 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "17:27:03 May 17, 2014" + +# Revisions + +PROJECT_REVISION = "ossc" diff --git a/ossc.qsf b/ossc.qsf new file mode 100644 index 0000000..03cd273 --- /dev/null +++ b/ossc.qsf @@ -0,0 +1,235 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 17:27:03 May 17, 2014 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# ossc_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE15E22C8 +set_global_assignment -name TOP_LEVEL_ENTITY ossc +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:27:03 MAY 17, 2014" +set_global_assignment -name LAST_QUARTUS_VERSION 15.1.0 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name EDA_SIMULATION_TOOL "" +set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" + + +set_location_assignment PIN_25 -to clk27 +set_location_assignment PIN_99 -to reset_n +set_location_assignment PIN_23 -to ir_rx + +#============================================================ +# TVP7002 +#============================================================ +set_location_assignment PIN_52 -to R_in[0] +set_location_assignment PIN_53 -to R_in[1] +set_location_assignment PIN_54 -to R_in[2] +set_location_assignment PIN_55 -to R_in[3] +set_location_assignment PIN_58 -to R_in[4] +set_location_assignment PIN_59 -to R_in[5] +set_location_assignment PIN_60 -to R_in[6] +set_location_assignment PIN_61 -to R_in[7] +set_location_assignment PIN_88 -to B_in[7] +set_location_assignment PIN_87 -to B_in[6] +set_location_assignment PIN_86 -to B_in[5] +set_location_assignment PIN_85 -to B_in[4] +set_location_assignment PIN_83 -to B_in[3] +set_location_assignment PIN_80 -to B_in[2] +set_location_assignment PIN_77 -to B_in[1] +set_location_assignment PIN_89 -to PCLK_in +set_location_assignment PIN_76 -to B_in[0] +set_location_assignment PIN_90 -to HSYNC_in +set_location_assignment PIN_91 -to VSYNC_in +set_location_assignment PIN_98 -to FID_in +set_location_assignment PIN_72 -to G_in[7] +set_location_assignment PIN_71 -to G_in[6] +set_location_assignment PIN_69 -to G_in[5] +set_location_assignment PIN_68 -to G_in[4] +set_location_assignment PIN_67 -to G_in[3] +set_location_assignment PIN_66 -to G_in[2] +set_location_assignment PIN_65 -to G_in[1] +set_location_assignment PIN_64 -to G_in[0] + +#============================================================ +# HDMITX +#============================================================ +set_location_assignment PIN_113 -to HDMI_TX_PCLK +set_location_assignment PIN_111 -to HDMI_TX_BD[3] +set_location_assignment PIN_112 -to HDMI_TX_BD[4] +set_location_assignment PIN_110 -to HDMI_TX_BD[2] +set_location_assignment PIN_106 -to HDMI_TX_BD[1] +set_location_assignment PIN_105 -to HDMI_TX_BD[0] +set_location_assignment PIN_104 -to HDMI_TX_DE +set_location_assignment PIN_103 -to HDMI_TX_HS +set_location_assignment PIN_101 -to HDMI_TX_VS +set_location_assignment PIN_114 -to HDMI_TX_BD[5] +set_location_assignment PIN_115 -to HDMI_TX_BD[6] +set_location_assignment PIN_119 -to HDMI_TX_BD[7] +set_location_assignment PIN_120 -to HDMI_TX_GD[0] +set_location_assignment PIN_121 -to HDMI_TX_GD[1] +set_location_assignment PIN_125 -to HDMI_TX_GD[2] +set_location_assignment PIN_132 -to HDMI_TX_GD[3] +set_location_assignment PIN_133 -to HDMI_TX_GD[4] +set_location_assignment PIN_134 -to HDMI_TX_GD[5] +set_location_assignment PIN_135 -to HDMI_TX_GD[6] +set_location_assignment PIN_136 -to HDMI_TX_GD[7] +set_location_assignment PIN_137 -to HDMI_TX_RD[0] +set_location_assignment PIN_141 -to HDMI_TX_RD[1] +set_location_assignment PIN_142 -to HDMI_TX_RD[2] +set_location_assignment PIN_143 -to HDMI_TX_RD[3] +set_location_assignment PIN_144 -to HDMI_TX_RD[4] +set_location_assignment PIN_7 -to HDMI_TX_RD[5] +set_location_assignment PIN_10 -to HDMI_TX_RD[6] +set_location_assignment PIN_11 -to HDMI_TX_RD[7] +set_location_assignment PIN_100 -to HDMI_TX_INT_N +set_location_assignment PIN_127 -to HDMI_TX_MODE + +#============================================================ +# SD card +#============================================================ +set_location_assignment PIN_32 -to SD_CLK +set_location_assignment PIN_31 -to SD_CMD +set_location_assignment PIN_33 -to SD_DAT[0] +set_location_assignment PIN_39 -to SD_DAT[1] +set_location_assignment PIN_28 -to SD_DAT[2] +set_location_assignment PIN_30 -to SD_DAT[3] + +#============================================================ +# Leds +#============================================================ +set_location_assignment PIN_44 -to LED_G +set_location_assignment PIN_46 -to LED_R + +#============================================================ +# I2C +#============================================================ +set_location_assignment PIN_49 -to sda +set_location_assignment PIN_50 -to scl + +#============================================================ +# Char LCD +#============================================================ +set_location_assignment PIN_42 -to LCD_RS +set_location_assignment PIN_43 -to LCD_CS_N +set_location_assignment PIN_51 -to LCD_BL + +#============================================================ +# Buttons +#============================================================ +set_location_assignment PIN_129 -to btn[1] +set_location_assignment PIN_128 -to btn[0] + + +set_instance_assignment -name PLL_COMPENSATE ON -to G_in +set_instance_assignment -name PLL_COMPENSATE ON -to FID_in +set_instance_assignment -name PLL_COMPENSATE ON -to HSYNC_in +set_instance_assignment -name PLL_COMPENSATE ON -to R_in +set_instance_assignment -name PLL_COMPENSATE ON -to VSYNC_in +set_instance_assignment -name PLL_COMPENSATE ON -to B_in + + +set_global_assignment -name USE_CONFIGURATION_DEVICE ON +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + + +set_global_assignment -name SEARCH_PATH rtl +set_global_assignment -name CYCLONEIII_CONFIGURATION_DEVICE EPCS16 + +set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005 +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF + +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name SMART_RECOMPILE OFF + +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL + +set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION OFF + +set_global_assignment -name OPTIMIZATION_MODE BALANCED +set_global_assignment -name ALLOW_REGISTER_RETIMING OFF + +set_global_assignment -name ENABLE_OCT_DONE OFF +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF + +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name GENERATE_RBF_FILE ON + +set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE 50% + + + +#set_location_assignment PLL_4 -to "scanconverter:scanconverter_inst|pll_3x:pll_linetriple|altpll:altpll_component|pll_3x_altpll:auto_generated|pll1" +#set_location_assignment PLL_3 -to "scanconverter:scanconverter_inst|pll_3x_lowfreq:pll_linetriple_lowfreq|altpll:altpll_component|pll_3x_lowfreq_altpll:auto_generated|pll1" +#set_location_assignment PLL_1 -to "scanconverter:scanconverter_inst|pll_2x:pll_linedouble|altpll:altpll_component|pll_2x_altpll:auto_generated|pll1" + + +set_global_assignment -name VERILOG_FILE rtl/videogen.v +set_global_assignment -name QIP_FILE software/sys_controller/mem_init/meminit.qip +set_global_assignment -name VERILOG_FILE rtl/ir_rcv.v +set_global_assignment -name SDC_FILE ossc.sdc +set_global_assignment -name QSYS_FILE sys.qsys +set_global_assignment -name VERILOG_FILE rtl/ossc.v +set_global_assignment -name VERILOG_FILE rtl/scanconverter.v +set_global_assignment -name QIP_FILE rtl/linebuf.qip +set_global_assignment -name QIP_FILE rtl/pll_2x.qip +set_global_assignment -name QIP_FILE rtl/pll_3x.qip +set_global_assignment -name QIP_FILE rtl/pll_3x_lowfreq.qip +set_global_assignment -name CDF_FILE output_files/Chain1.cdf + + + +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/ossc.sdc b/ossc.sdc new file mode 100644 index 0000000..d0cd6d2 --- /dev/null +++ b/ossc.sdc @@ -0,0 +1,102 @@ +### CPU clock constraints ### + +create_clock -period 27MHz -name clk27 [get_ports clk27] + +set_input_delay -clock clk27 0 [get_ports {sda scl ir_rx HDMI_TX_INT_N SD_CMD SD_DAT* btn* *ALTERA_DATA0}] +set_false_path -to {sys:sys_inst|sys_pio_1:pio_1|readdata*} + +### Scanconverter clock constraints ### + +create_clock -period 108MHz -name pclk_hdtv [get_ports PCLK_in] +create_clock -period 27MHz -name pclk_ldtv_hs_M0 [get_ports PCLK_in] -add +create_clock -period 20MHz -name pclk_ldtv_hs_M1 [get_ports PCLK_in] -add +create_clock -period 13.5MHz -name pclk_sdtv [get_ports PCLK_in] -add +create_clock -period 6.7MHz -name pclk_ldtv_M2 [get_ports PCLK_in] -add +create_clock -period 5.4MHz -name pclk_ldtv_M3 [get_ports PCLK_in] -add + +#derive_pll_clocks +create_generated_clock -master_clock pclk_sdtv -source {scanconverter_inst|pll_linedouble|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 2 -duty_cycle 50.00 -name pclk_2x {scanconverter_inst|pll_linedouble|altpll_component|auto_generated|pll1|clk[0]} +create_generated_clock -master_clock pclk_ldtv_hs_M0 -source {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_M0 {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|clk[0]} +create_generated_clock -master_clock pclk_ldtv_hs_M1 -source {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_M1 {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|clk[0]} -add +create_generated_clock -master_clock pclk_ldtv_hs_M1 -source {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 4 -duty_cycle 50.00 -name pclk_4x_M1 {scanconverter_inst|pll_linetriple|altpll_component|auto_generated|pll1|clk[1]} +create_generated_clock -master_clock pclk_ldtv_M2 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_h1x_M2 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[0]} +create_generated_clock -master_clock pclk_ldtv_M2 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 12 -duty_cycle 50.00 -name pclk_3x_h4x_M2 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[1]} +create_generated_clock -master_clock pclk_ldtv_M3 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 3 -duty_cycle 50.00 -name pclk_3x_h1x_M3 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[0]} -add +create_generated_clock -master_clock pclk_ldtv_M3 -source {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|inclk[0]} -multiply_by 15 -duty_cycle 50.00 -name pclk_3x_h5x_M3 {scanconverter_inst|pll_linetriple_lowfreq|altpll_component|auto_generated|pll1|clk[2]} + +derive_clock_uncertainty + +# input delay constraints +set critinputs [get_ports {R_in* G_in* B_in* FID_in HSYNC_in VSYNC_in}] +set_input_delay -clock pclk_sdtv -min 0 $critinputs +set_input_delay -clock pclk_sdtv -max 1.5 $critinputs +set_input_delay -clock pclk_hdtv -min 0 $critinputs -add_delay +set_input_delay -clock pclk_hdtv -max 1.5 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_M2 -min 0 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_M2 -max 1.5 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_M3 -min 0 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_M3 -max 1.5 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_hs_M0 -min 0 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_hs_M0 -max 1.5 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_hs_M1 -min 0 $critinputs -add_delay +set_input_delay -clock pclk_ldtv_hs_M1 -max 1.5 $critinputs -add_delay + +# output delay constraints (TODO: add vsync) +set critoutputs_hdmi {HDMI_TX_RD* HDMI_TX_GD* HDMI_TX_BD* HDMI_TX_DE HDMI_TX_HS} +set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_hdtv 0 $critoutputs_hdmi +set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_2x 0 $critoutputs_hdmi -add_delay +set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_3x_M0 0 $critoutputs_hdmi -add_delay +set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_4x_M1 0 $critoutputs_hdmi -add_delay +set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_3x_h4x_M2 0 $critoutputs_hdmi -add_delay +set_output_delay -reference_pin HDMI_TX_PCLK -clock pclk_3x_h5x_M3 0 $critoutputs_hdmi -add_delay +set_false_path -to [remove_from_collection [all_outputs] $critoutputs_hdmi] + + +### CPU/scanconverter clock relations ### + +# Set pixel clocks as exclusive clocks +set_clock_groups -exclusive \ +-group {pclk_hdtv} \ +-group {pclk_sdtv pclk_2x} \ +-group {pclk_ldtv_hs_M0 pclk_3x_M0} \ +-group {pclk_ldtv_hs_M1 pclk_3x_M1 pclk_4x_M1} \ +-group {pclk_ldtv_M2 pclk_3x_h1x_M2 pclk_3x_h4x_M2} \ +-group {pclk_ldtv_M3 pclk_3x_h1x_M3 pclk_3x_h5x_M3} + +# Treat CPU clock asynchronous to pixel clocks +set_clock_groups -asynchronous -group {clk27} + +# Filter out impossible output mux combinations +set clkmuxregs [get_cells {scanconverter:scanconverter_inst|R_out[*] scanconverter:scanconverter_inst|G_out[*] scanconverter:scanconverter_inst|B_out[*] scanconverter:scanconverter_inst|HSYNC_out scanconverter:scanconverter_inst|DATA_enable scanconverter:scanconverter_inst|*_pp1*}] +set clkmuxnodes [get_pins {scanconverter_inst|linebuf_*|altsyncram_*|auto_generated|ram_*|portbaddr*}] +set_false_path -from [get_clocks {pclk_ldtv* pclk_sdtv}] -through $clkmuxregs +set_false_path -from pclk_3x_M1 -through [remove_from_collection $clkmuxregs {scanconverter:scanconverter_inst|DATA_enable_pp1* scanconverter:scanconverter_inst|HSYNC_pp1*}] -to pclk_4x_M1 +set_false_path -from pclk_3x_M1 -through $clkmuxnodes -to pclk_4x_M1 + +# Ignore paths from registers which are updated only at the end of vsync +set_false_path -from [get_cells {scanconverter_inst|H_* scanconverter_inst|V_* scanconverter:scanconverter_inst|lines_*}] + +# Ignore paths from registers which are updated only at the end of hsync +set_false_path -from [get_cells {scanconverter:scanconverter_inst|vcnt_* scanconverter:scanconverter_inst|line_idx}] + +# Ignore following clock transfers +set_false_path -from [get_clocks pclk_2x] -to [get_clocks pclk_sdtv] +set_false_path -from [get_clocks pclk_3x_M*] -to [get_clocks {pclk_ldtv_hs_M*}] +set_false_path -from [get_clocks pclk_4x_M1] -to [get_clocks {pclk_ldtv_hs_M1 pclk_3x_M1}] +set_false_path -from [get_clocks pclk_3x_h4x_M2] -to [get_clocks {pclk_ldtv_M2 pclk_3x_h1x_M2}] +set_false_path -from [get_clocks pclk_3x_h5x_M3] -to [get_clocks {pclk_ldtv_M3 pclk_3x_h1x_M3}] +set_false_path -from [get_clocks pclk_3x_h1x_M*] -to [get_clocks {pclk_ldtv_M*}] + + +### JTAG Signal Constraints ### + +#constrain the TCK port +#create_clock -name tck -period "10MHz" [get_ports altera_reserved_tck] +#cut all paths to and from tck +set_clock_groups -exclusive -group [get_clocks altera_reserved_tck] +#constrain the TDI port +set_input_delay -clock altera_reserved_tck 20 [get_ports altera_reserved_tdi] +#constrain the TMS port +set_input_delay -clock altera_reserved_tck 20 [get_ports altera_reserved_tms] +#constrain the TDO port +#set_output_delay -clock altera_reserved_tck 20 [get_ports altera_reserved_tdo] diff --git a/rtl/ir_rcv.v b/rtl/ir_rcv.v new file mode 100644 index 0000000..63ed120 --- /dev/null +++ b/rtl/ir_rcv.v @@ -0,0 +1,168 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +`define STATE_IDLE 2'b00 +`define STATE_LEADVERIFY 2'b01 +`define STATE_DATARCV 2'b10 + +module ir_rcv ( + input clk27, + input reset_n, + input ir_rx, + output reg [15:0] ir_code, + output reg ir_code_ack +); + +// 20ns clock period + +parameter LEADCODE_LO_THOLD = 124200; //4.60ms +parameter LEADCODE_HI_THOLD = 113400; //4.20ms +parameter LEADCODE_HI_RPT_THOLD = 56700; //2.1ms +parameter RPT_RELEASE_THOLD = 3240000; //120ms +parameter BIT_ONE_THOLD = 22410; //0.83ms +parameter BIT_DETECT_THOLD = 10800; //0.4ms +parameter IDLE_THOLD = 141557; //5.24ms + +reg [1:0] state; // 3 states +reg [31:0] databuf; // temp. buffer +reg [5:0] bits_detected; // max. 63, effectively between 0 and 33 +reg [17:0] act_cnt; // max. 5.2ms +reg [17:0] leadvrf_cnt; // max. 5.2ms +reg [17:0] datarcv_cnt; // max. 5.2ms +reg [22:0] rpt_cnt; // max. 166ms + +// activity when signal is low +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + act_cnt <= 0; + else + begin + if ((state == `STATE_IDLE) & (~ir_rx)) + act_cnt <= act_cnt + 1'b1; + else + act_cnt <= 0; + end +end + +// lead code verify counter +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + leadvrf_cnt <= 0; + else + begin + if ((state == `STATE_LEADVERIFY) & ir_rx) + leadvrf_cnt <= leadvrf_cnt + 1'b1; + else + leadvrf_cnt <= 0; + end +end + + +// '0' and '1' are differentiated by high phase duration preceded by constant length low phase +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + datarcv_cnt <= 0; + bits_detected <= 0; + databuf <= 0; + end + else + begin + if (state == `STATE_DATARCV) + begin + if (ir_rx) + datarcv_cnt <= datarcv_cnt + 1'b1; + else + datarcv_cnt <= 0; + + if (datarcv_cnt == BIT_DETECT_THOLD) + bits_detected <= bits_detected + 1'b1; + + if (datarcv_cnt == BIT_ONE_THOLD) + databuf[32-bits_detected] <= 1'b1; + end + else + begin + datarcv_cnt <= 0; + bits_detected <= 0; + databuf <= 0; + end + end +end + +// read and validate data after 32 bits detected (last bit may change to '1' at any time) +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + ir_code_ack <= 1'b0; + ir_code <= 16'h00000000; + end + else + begin + if ((bits_detected == 32) & (databuf[31:24] == ~databuf[23:16]) & (databuf[15:8] == ~databuf[7:0])) + begin + ir_code <= {databuf[31:24], databuf[15:8]}; + ir_code_ack <= 1'b1; + end + else if (rpt_cnt >= RPT_RELEASE_THOLD) + begin + ir_code <= 16'h00000000; + ir_code_ack <= 1'b0; + end + else + ir_code_ack <= 1'b0; + end +end + +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + state <= `STATE_IDLE; + rpt_cnt <= 0; + end + else + begin + rpt_cnt <= rpt_cnt + 1'b1; + + case (state) + `STATE_IDLE: + if (act_cnt >= LEADCODE_LO_THOLD) + state <= `STATE_LEADVERIFY; + `STATE_LEADVERIFY: + begin + if (leadvrf_cnt == LEADCODE_HI_RPT_THOLD) + rpt_cnt <= 0; + if (leadvrf_cnt >= LEADCODE_HI_THOLD) + state <= `STATE_DATARCV; + end + `STATE_DATARCV: + if ((datarcv_cnt >= IDLE_THOLD) | (bits_detected >= 33)) + state <= `STATE_IDLE; + default: + state <= `STATE_IDLE; + endcase + end +end + +endmodule diff --git a/rtl/linebuf.qip b/rtl/linebuf.qip new file mode 100644 index 0000000..954c30e --- /dev/null +++ b/rtl/linebuf.qip @@ -0,0 +1,6 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" +set_global_assignment -name IP_TOOL_VERSION "15.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "linebuf.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "linebuf_inst.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "linebuf_bb.v"] diff --git a/rtl/linebuf.v b/rtl/linebuf.v new file mode 100644 index 0000000..e9dabce --- /dev/null +++ b/rtl/linebuf.v @@ -0,0 +1,216 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: linebuf.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 15.1.0 Build 185 10/21/2015 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 1991-2015 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus Prime License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module linebuf ( + data, + rdaddress, + rdclock, + wraddress, + wrclock, + wren, + q); + + input [23:0] data; + input [11:0] rdaddress; + input rdclock; + input [11:0] wraddress; + input wrclock; + input wren; + output [23:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 wrclock; + tri0 wren; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [23:0] sub_wire0; + wire [23:0] q = sub_wire0[23:0]; + + altsyncram altsyncram_component ( + .address_a (wraddress), + .address_b (rdaddress), + .clock0 (wrclock), + .clock1 (rdclock), + .data_a (data), + .wren_a (wren), + .q_b (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({24{1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK1", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone IV E", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 4096, + altsyncram_component.numwords_b = 4096, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "CLOCK1", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.widthad_a = 12, + altsyncram_component.widthad_b = 12, + altsyncram_component.width_a = 24, + altsyncram_component.width_b = 24, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLRdata NUMERIC "0" +// Retrieval info: PRIVATE: CLRq NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren NUMERIC "0" +// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRwren NUMERIC "0" +// Retrieval info: PRIVATE: Clock NUMERIC "1" +// Retrieval info: PRIVATE: Clock_A NUMERIC "0" +// Retrieval info: PRIVATE: Clock_B NUMERIC "0" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_B" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MEMSIZE NUMERIC "98304" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2" +// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "1" +// Retrieval info: PRIVATE: REGrdaddress NUMERIC "1" +// Retrieval info: PRIVATE: REGrren NUMERIC "1" +// Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +// Retrieval info: PRIVATE: REGwren NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" +// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +// Retrieval info: PRIVATE: VarWidth NUMERIC "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "24" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "24" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "24" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "24" +// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "0" +// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: enable NUMERIC "0" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADDRESS_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "4096" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK1" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "12" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "24" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "24" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: data 0 0 24 0 INPUT NODEFVAL "data[23..0]" +// Retrieval info: USED_PORT: q 0 0 24 0 OUTPUT NODEFVAL "q[23..0]" +// Retrieval info: USED_PORT: rdaddress 0 0 12 0 INPUT NODEFVAL "rdaddress[11..0]" +// Retrieval info: USED_PORT: rdclock 0 0 0 0 INPUT NODEFVAL "rdclock" +// Retrieval info: USED_PORT: wraddress 0 0 12 0 INPUT NODEFVAL "wraddress[11..0]" +// Retrieval info: USED_PORT: wrclock 0 0 0 0 INPUT VCC "wrclock" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND "wren" +// Retrieval info: CONNECT: @address_a 0 0 12 0 wraddress 0 0 12 0 +// Retrieval info: CONNECT: @address_b 0 0 12 0 rdaddress 0 0 12 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 wrclock 0 0 0 0 +// Retrieval info: CONNECT: @clock1 0 0 0 0 rdclock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 24 0 data 0 0 24 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 24 0 @q_b 0 0 24 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf_inst.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL linebuf_bb.v TRUE +// Retrieval info: LIB_FILE: altera_mf diff --git a/rtl/ossc.v b/rtl/ossc.v new file mode 100644 index 0000000..1c2b055 --- /dev/null +++ b/rtl/ossc.v @@ -0,0 +1,197 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +//`define DEBUG +`define VIDEOGEN + +module ossc ( + input clk27, + input ir_rx, + inout scl, + inout sda, + input [1:0] btn, + input [7:0] R_in, + input [7:0] G_in, + input [7:0] B_in, + input FID_in, + input VSYNC_in, + input HSYNC_in, + input PCLK_in, + output [7:0] HDMI_TX_RD, + output [7:0] HDMI_TX_GD, + output [7:0] HDMI_TX_BD, + output HDMI_TX_DE, + output HDMI_TX_HS, + output HDMI_TX_VS, + output HDMI_TX_PCLK, + input HDMI_TX_INT_N, + input HDMI_TX_MODE, + output reset_n, + output LED_G, + output LED_R, + output LCD_RS, + output LCD_CS_N, + output LCD_BL, + output SD_CLK, + inout SD_CMD, + inout [3:0] SD_DAT +); + +wire cpu_reset_n; +wire [7:0] sys_ctrl; +wire h_unstable; +wire [2:0] pclk_lock; +wire [2:0] pll_lock_lost; +wire [31:0] h_info; +wire [31:0] v_info; +wire [10:0] lines_out; +wire [1:0] fpga_vsyncgen; + +wire [15:0] ir_code; + +wire [7:0] R_out, G_out, B_out; +wire HSYNC_out; +wire VSYNC_out; +wire PCLK_out; +wire DATA_enable; + +wire [7:0] R_out_videogen, G_out_videogen, B_out_videogen; +wire HSYNC_out_videogen; +wire VSYNC_out_videogen; +wire PCLK_out_videogen; +wire DATA_enable_videogen; + +wire [7:0] lcd_ctrl; + +reg [3:0] reset_n_ctr; + +`ifdef DEBUG +assign LED_G = {clk27, PCLK_in}; +assign LED_R = {HSYNC_in, VSYNC_in}; +`else +//assign LED_G = {(pclk_lock != 3'b000), (ir_code != 0)}; +//assign LED_R = {(pll_lock_lost != 3'b000), h_unstable}; +assign LED_G = (ir_code == 0); +assign LED_R = (pll_lock_lost != 3'b000)|h_unstable; +`endif + +assign LCD_CS_N = lcd_ctrl[0]; +assign LCD_RS = lcd_ctrl[1]; +assign LCD_BL = sys_ctrl[1]; //reset_n in v1.2 PCB + +assign reset_n = sys_ctrl[0]; //HDMI_TX_RST_N in v1.2 PCB + +`ifdef VIDEOGEN +wire videogen_sel; +assign videogen_sel = ~sys_ctrl[2]; +assign HDMI_TX_RD = videogen_sel ? R_out_videogen : R_out; +assign HDMI_TX_GD = videogen_sel ? G_out_videogen : G_out; +assign HDMI_TX_BD = videogen_sel ? B_out_videogen : B_out; +assign HDMI_TX_HS = videogen_sel ? HSYNC_out_videogen : HSYNC_out; +assign HDMI_TX_VS = videogen_sel ? VSYNC_out_videogen : VSYNC_out; +assign HDMI_TX_PCLK = videogen_sel ? PCLK_out_videogen : PCLK_out; +assign HDMI_TX_DE = videogen_sel ? DATA_enable_videogen : DATA_enable; +`else +assign HDMI_TX_RD = R_out; +assign HDMI_TX_GD = G_out; +assign HDMI_TX_BD = B_out; +assign HDMI_TX_HS = HSYNC_out; +assign HDMI_TX_VS = VSYNC_out; +assign HDMI_TX_PCLK = PCLK_out; +assign HDMI_TX_DE = DATA_enable; +`endif + +always @(posedge clk27) +begin + if (reset_n_ctr == 4'b1000) + reset_n_reg <= 1'b1; + else + reset_n_ctr <= reset_n_ctr + 1'b1; +end + +assign cpu_reset_n = reset_n_reg; + +sys sys_inst( + .clk_clk (clk27), + .reset_reset_n (cpu_reset_n), + .pio_0_sys_ctrl_out_export (sys_ctrl), + .pio_1_controls_in_export ({13'b00000000000000, HDMI_TX_MODE, btn, ir_code}), + .pio_2_horizontal_info_out_export (h_info), + .pio_3_vertical_info_out_export (v_info), +`ifdef DEBUG + .pio_4_linecount_in_export ({8'h00, R_in, G_in, B_in}), +`else + .pio_4_linecount_in_export ({14'h0000, fpga_vsyncgen, 5'h00, lines_out}), +`endif + .pio_5_lcd_ctrl_out_export (lcd_ctrl), + .i2c_opencores_0_export_scl_pad_io (scl), + .i2c_opencores_0_export_sda_pad_io (sda), + .sdcard_0_b_SD_cmd (SD_CMD), + .sdcard_0_b_SD_dat (SD_DAT[0]), + .sdcard_0_b_SD_dat3 (SD_DAT[3]), + .sdcard_0_o_SD_clock (SD_CLK) +); + +scanconverter scanconverter_inst ( + .HSYNC_in (HSYNC_in), + .VSYNC_in (VSYNC_in), + .PCLK_in (PCLK_in), + .FID_in (FID_in), + .R_in (R_in), + .G_in (G_in), + .B_in (B_in), + .h_info (h_info), + .v_info (v_info), + .R_out (R_out), + .G_out (G_out), + .B_out (B_out), + .HSYNC_out (HSYNC_out), + .VSYNC_out (VSYNC_out), + .PCLK_out (PCLK_out), + .DATA_enable (DATA_enable), + .h_unstable (h_unstable), + .fpga_vsyncgen (fpga_vsyncgen), + .pclk_lock (pclk_lock), + .pll_lock_lost (pll_lock_lost), + .lines_out (lines_out) +); + +ir_rcv ir0 ( + .clk27 (clk27), + .reset_n (reset_n_reg), + .ir_rx (ir_rx), + .ir_code (ir_code), + .ir_code_ack () +); + +`ifdef VIDEOGEN +videogen vg0 ( + .clk27 (clk27), + .reset_n (reset_n_reg & videogen_sel), + .R_out (R_out_videogen), + .G_out (G_out_videogen), + .B_out (B_out_videogen), + .HSYNC_out (HSYNC_out_videogen), + .VSYNC_out (VSYNC_out_videogen), + .PCLK_out (PCLK_out_videogen), + .ENABLE_out (DATA_enable_videogen) +); +`endif + +endmodule diff --git a/rtl/pll_2x.ppf b/rtl/pll_2x.ppf new file mode 100644 index 0000000..9736c2c --- /dev/null +++ b/rtl/pll_2x.ppf @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/rtl/pll_2x.qip b/rtl/pll_2x.qip new file mode 100644 index 0000000..0565949 --- /dev/null +++ b/rtl/pll_2x.qip @@ -0,0 +1,6 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "15.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_2x.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_2x_bb.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_2x.ppf"] diff --git a/rtl/pll_2x.v b/rtl/pll_2x.v new file mode 100644 index 0000000..6c7d33e --- /dev/null +++ b/rtl/pll_2x.v @@ -0,0 +1,320 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll_2x.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 15.1.0 Build 185 10/21/2015 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 1991-2015 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus Prime License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll_2x ( + areset, + inclk0, + c0, + locked); + + input areset; + input inclk0; + output c0; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire5 = 1'h0; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire locked = sub_wire2; + wire sub_wire3 = inclk0; + wire [1:0] sub_wire4 = {sub_wire5, sub_wire3}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire4), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "LOW", + altpll_component.clk0_divide_by = 1, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 2, + altpll_component.clk0_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 74074, + altpll_component.intended_device_family = "Cyclone IV E", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_2x", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "SOURCE_SYNCHRONOUS", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_UNUSED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "27.000000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "13.500" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_2x.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "74074" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_2x_bb.v TRUE +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/rtl/pll_3x.ppf b/rtl/pll_3x.ppf new file mode 100644 index 0000000..45ca1af --- /dev/null +++ b/rtl/pll_3x.ppf @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/rtl/pll_3x.qip b/rtl/pll_3x.qip new file mode 100644 index 0000000..0c861a4 --- /dev/null +++ b/rtl/pll_3x.qip @@ -0,0 +1,5 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "15.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_3x.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_3x.ppf"] diff --git a/rtl/pll_3x.v b/rtl/pll_3x.v new file mode 100644 index 0000000..ea4e476 --- /dev/null +++ b/rtl/pll_3x.v @@ -0,0 +1,348 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll_3x.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 15.1.0 Build 185 10/21/2015 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 1991-2015 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus Prime License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll_3x ( + areset, + inclk0, + c0, + c1, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire3; + wire [0:0] sub_wire6 = 1'h0; + wire [1:1] sub_wire2 = sub_wire0[1:1]; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire c1 = sub_wire2; + wire locked = sub_wire3; + wire sub_wire4 = inclk0; + wire [1:0] sub_wire5 = {sub_wire6, sub_wire4}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire5), + .clk (sub_wire0), + .locked (sub_wire3), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "LOW", + altpll_component.clk0_divide_by = 1, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 3, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 1, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 4, + altpll_component.clk1_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone IV E", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_3x", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "SOURCE_SYNCHRONOUS", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_UNUSED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "81.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "108.000000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "3" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "4" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_2x.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "3" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "4" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_bb.v FALSE +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/rtl/pll_3x_lowfreq.ppf b/rtl/pll_3x_lowfreq.ppf new file mode 100644 index 0000000..1d235e3 --- /dev/null +++ b/rtl/pll_3x_lowfreq.ppf @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/rtl/pll_3x_lowfreq.qip b/rtl/pll_3x_lowfreq.qip new file mode 100644 index 0000000..b4bc56d --- /dev/null +++ b/rtl/pll_3x_lowfreq.qip @@ -0,0 +1,6 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "15.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{Cyclone IV E}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_3x_lowfreq.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_3x_lowfreq_bb.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_3x_lowfreq.ppf"] diff --git a/rtl/pll_3x_lowfreq.v b/rtl/pll_3x_lowfreq.v new file mode 100644 index 0000000..8fc3638 --- /dev/null +++ b/rtl/pll_3x_lowfreq.v @@ -0,0 +1,376 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll_3x_lowfreq.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 15.1.0 Build 185 10/21/2015 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 1991-2015 Altera Corporation. All rights reserved. +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, the Altera Quartus Prime License Agreement, +//the Altera MegaCore Function License Agreement, or other +//applicable license agreement, including, without limitation, +//that your use is for the sole purpose of programming logic +//devices manufactured by Altera and sold by Altera or its +//authorized distributors. Please refer to the applicable +//agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll_3x_lowfreq ( + areset, + inclk0, + c0, + c1, + c2, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output c2; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire4; + wire [0:0] sub_wire7 = 1'h0; + wire [2:2] sub_wire3 = sub_wire0[2:2]; + wire [1:1] sub_wire2 = sub_wire0[1:1]; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire c1 = sub_wire2; + wire c2 = sub_wire3; + wire locked = sub_wire4; + wire sub_wire5 = inclk0; + wire [1:0] sub_wire6 = {sub_wire7, sub_wire5}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire6), + .clk (sub_wire0), + .locked (sub_wire4), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "LOW", + altpll_component.clk0_divide_by = 1, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 3, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 1, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 12, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk2_divide_by = 1, + altpll_component.clk2_duty_cycle = 50, + altpll_component.clk2_multiply_by = 15, + altpll_component.clk2_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 149253, + altpll_component.intended_device_family = "Cyclone IV E", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_3x_lowfreq", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "SOURCE_SYNCHRONOUS", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_USED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "1" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "20.100000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "80.400002" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.500000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "6.700" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "3" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "12" +// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "15" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_2x.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLK2 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "LOW" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "3" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "12" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "15" +// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "149253" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SOURCE_SYNCHRONOUS" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_3x_lowfreq_bb.v TRUE +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/rtl/scanconverter.v b/rtl/scanconverter.v new file mode 100644 index 0000000..156ea26 --- /dev/null +++ b/rtl/scanconverter.v @@ -0,0 +1,682 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +`define TRUE 1'b1 +`define FALSE 1'b0 +`define HI 1'b1 +`define LO 1'b0 + +`define LINEMULT_DISABLE 2'h0 +`define LINEMULT_DOUBLE 2'h1 +`define LINEMULT_TRIPLE 2'h2 + +`define LINETRIPLE_M0 2'h0 +`define LINETRIPLE_M1 2'h1 +`define LINETRIPLE_M2 2'h2 +`define LINETRIPLE_M3 2'h3 + +`define VSYNCGEN_LEN 6 +`define VSYNCGEN_GENMID_BIT 0 +`define VSYNCGEN_CHOPMID_BIT 1 + +`define FID_EVEN 1'b0 +`define FID_ODD 1'b1 + +`define MIN_VALID_LINES 256 //power of 2 optimization -> ignore lower bits with comparison +`define FALSE_FIELD (fpga_vsyncgen[`VSYNCGEN_CHOPMID_BIT] & (FID_in == `FID_ODD)) + +`define VSYNC_LEADING_EDGE ((prev_vs == `HI) & (VSYNC_in == `LO)) +`define VSYNC_TRAILING_EDGE ((prev_vs == `LO) & (VSYNC_in == `HI)) + +`define HSYNC_LEADING_EDGE ((prev_hs == `HI) & (HSYNC_in == `LO)) +`define HSYNC_TRAILING_EDGE ((prev_hs == `LO) & (HSYNC_in == `HI)) + +module scanconverter ( + input [7:0] R_in, + input [7:0] G_in, + input [7:0] B_in, + input FID_in, + input VSYNC_in, + input HSYNC_in, + input PCLK_in, + input [31:0] h_info, + input [31:0] v_info, + output reg [7:0] R_out, + output reg [7:0] G_out, + output reg [7:0] B_out, + output reg HSYNC_out, + output reg VSYNC_out, + output PCLK_out, + output reg DATA_enable, + output h_unstable, + output reg [1:0] fpga_vsyncgen, + output [2:0] pclk_lock, + output [2:0] pll_lock_lost, + output [10:0] lines_out +); + +wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_3x_h1x, pclk_3x_h4x, pclk_3x_h5x; +wire pclk_out_1x, pclk_out_2x, pclk_out_3x, pclk_out_4x, pclk_out_3x_h4x, pclk_out_3x_h5x; +wire linebuf_rdclock; + +wire pclk_act; +wire [1:0] slid_act; + +wire pclk_2x_lock, pclk_3x_lock, pclk_3x_lowfreq_lock; + +wire HSYNC_act, VSYNC_act; +reg HSYNC_1x, HSYNC_2x, HSYNC_3x, HSYNC_3x_h1x, HSYNC_pp1; +reg VSYNC_1x, VSYNC_2x, VSYNC_pp1; + +reg [11:0] HSYNC_start; + +reg FID_prev; + +wire DATA_enable_act; +reg DATA_enable_pp1; + +wire [11:0] linebuf_hoffset; //Offset for line (max. 2047 pixels), MSB indicates which line is read/written +wire [11:0] hcnt_act; +reg [11:0] hcnt_1x, hcnt_2x, hcnt_3x, hcnt_4x, hcnt_3x_h1x, hcnt_3x_h4x, hcnt_3x_h5x; + +wire [10:0] vcnt_act; +reg [10:0] vcnt_1x, vcnt_1x_tvp, vcnt_2x, lines_1x, lines_2x; //max. 2047 +reg [9:0] vcnt_3x, vcnt_3x_h1x, lines_3x, lines_3x_h1x; //max. 1023 + +reg h_enable_3x_prev4x, h_enable_3x_prev3x_h4x, h_enable_3x_prev3x_h5x; +reg [1:0] hcnt_3x_h4x_ctr; +reg [1:0] hcnt_3x_h5x_ctr; + +reg pclk_1x_prev3x, pclk_1x_prev3x_h1x, pclk_1x_prev3x_h4x; +reg [1:0] pclk_3x_cnt, pclk_3x_h1x_cnt; +reg [3:0] pclk_3x_h4x_cnt; + +// Data enable +reg h_enable_1x, v_enable_1x; +reg h_enable_2x, v_enable_2x; +reg h_enable_3x, h_enable_3x_h1x, v_enable_3x, v_enable_3x_h1x; + +reg prev_hs, prev_vs; +reg [11:0] hmax[0:1]; +reg line_idx; + +reg [23:0] warn_h_unstable, warn_pll_lock_lost, warn_pll_lock_lost_3x, warn_pll_lock_lost_3x_lowfreq; + +reg [10:0] H_ACTIVE; //max. 2047 +reg [7:0] H_BACKPORCH; //max. 255 +reg [10:0] V_ACTIVE; //max. 2047 +reg [5:0] V_BACKPORCH; //max. 63 +reg V_SCANLINES; +reg V_SCANLINEDIR; +reg V_SCANLINEID; +reg [7:0] V_SCANLINESTR; +reg [5:0] V_MASK; +reg [1:0] H_LINEMULT; +reg [1:0] H_L3MODE; +reg [5:0] H_MASK; + +//8 bits per component -> 16.7M colors +reg [7:0] R_1x, G_1x, B_1x, R_pp1, G_pp1, B_pp1; +wire [7:0] R_lbuf, G_lbuf, B_lbuf; +wire [7:0] R_act, G_act, B_act; + + +assign pclk_1x = PCLK_in; +assign pclk_lock = {pclk_2x_lock, pclk_3x_lock, pclk_3x_lowfreq_lock}; + +//Output sampled at the rising edge of active pclk +assign pclk_out_1x = PCLK_in; +assign pclk_out_2x = pclk_2x; +assign pclk_out_3x = pclk_3x; +assign pclk_out_4x = pclk_4x; +assign pclk_out_3x_h4x = pclk_3x_h4x; +assign pclk_out_3x_h5x = pclk_3x_h5x; + +//Scanline generation +function [8:0] apply_scanlines; + input enable; + input dir; + input [8:0] data; + input [8:0] str; + input [1:0] actid; + input [1:0] lineid; + input pixid; + begin + if (enable & (dir == 1'b0) & (actid == lineid)) + apply_scanlines = (data > str) ? (data-str) : 8'h00; + else if (enable & (dir == 1'b1) & (actid == pixid)) + apply_scanlines = (data > str) ? (data-str) : 8'h00; + else + apply_scanlines = data; + end + endfunction + +//Border masking +function [8:0] apply_mask; + input enable; + input [8:0] data; + input [11:0] hoffset; + input [11:0] hstart; + input [11:0] hend; + input [10:0] voffset; + input [10:0] vstart; + input [10:0] vend; + begin + if (enable & ((hoffset < hstart) | (hoffset >= hend) | (voffset < vstart) | (voffset >= vend))) + apply_mask = 8'h00; + else + apply_mask = data; + //apply_mask = (hoffset[0] ^ voffset[0]) ? 8'b11111111 : 8'b00000000; + end + endfunction + + +//Mux for active data selection +// +//Possible clock transfers: +// +// L3_MODE1: pclk_3x -> pclk_4x +// L3_MODE2: pclk_3x_h1x -> pclk_3x_h4x +// L3_MODE3: pclk_3x_h1x -> pclk_3x_h5x +// +//List of critical signals: +// DATA_enable_act, HSYNC_act +// +//Non-critical signals and inactive clock combinations filtered out in SDC +always @(*) +begin + case (H_LINEMULT) + `LINEMULT_DISABLE: begin + R_act = R_1x; + G_act = G_1x; + B_act = B_1x; + DATA_enable_act = (h_enable_1x & v_enable_1x); + PCLK_out = pclk_out_1x; + HSYNC_act = HSYNC_1x; + VSYNC_act = VSYNC_1x; + lines_out = lines_1x; + linebuf_rdclock = 0; + linebuf_hoffset = 0; + pclk_act = pclk_1x; + slid_act = {1'b0, vcnt_1x[0]}; + hcnt_act = hcnt_1x; + vcnt_act = vcnt_1x; + end + `LINEMULT_DOUBLE: begin + R_act = R_lbuf; + G_act = G_lbuf; + B_act = B_lbuf; + DATA_enable_act = (h_enable_2x & v_enable_2x); + PCLK_out = pclk_out_2x; + HSYNC_act = HSYNC_2x; + VSYNC_act = VSYNC_2x; + lines_out = lines_2x; + linebuf_rdclock = pclk_2x; + linebuf_hoffset = hcnt_2x; + pclk_act = pclk_2x; + slid_act = {1'b0, vcnt_2x[0]}; + hcnt_act = hcnt_2x; + vcnt_act = vcnt_2x>>1; + end + `LINEMULT_TRIPLE: begin + R_act = R_lbuf; + G_act = G_lbuf; + B_act = B_lbuf; + VSYNC_act = VSYNC_1x; + case (H_L3MODE) + `LINETRIPLE_M0: begin + DATA_enable_act = (h_enable_3x & v_enable_3x); + PCLK_out = pclk_out_3x; + HSYNC_act = HSYNC_3x; + lines_out = {1'b0, lines_3x}; + linebuf_rdclock = pclk_3x; + linebuf_hoffset = hcnt_3x; + pclk_act = pclk_3x; + hcnt_act = hcnt_3x; + vcnt_act = vcnt_3x/2'h3; //divider generated + slid_act = (vcnt_3x % 2'h3); + end + `LINETRIPLE_M1: begin + DATA_enable_act = (h_enable_3x & v_enable_3x); + PCLK_out = pclk_out_4x; + HSYNC_act = HSYNC_3x; + lines_out = {1'b0, lines_3x}; + linebuf_rdclock = pclk_4x; + linebuf_hoffset = hcnt_4x; + pclk_act = pclk_4x; + hcnt_act = hcnt_4x; + vcnt_act = vcnt_3x/2'h3; //divider generated + slid_act = (vcnt_3x % 2'h3); + end + `LINETRIPLE_M2: begin + DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x); + PCLK_out = pclk_out_3x_h4x; + HSYNC_act = HSYNC_3x_h1x; + lines_out = {1'b0, lines_3x_h1x}; + linebuf_rdclock = pclk_3x_h4x; + linebuf_hoffset = hcnt_3x_h4x; + pclk_act = pclk_3x_h4x; + hcnt_act = hcnt_3x_h4x; + vcnt_act = vcnt_3x_h1x/2'h3; //divider generated + slid_act = (vcnt_3x_h1x % 2'h3); + end + `LINETRIPLE_M3: begin + DATA_enable_act = (h_enable_3x_h1x & v_enable_3x_h1x); + PCLK_out = pclk_out_3x_h5x; + HSYNC_act = HSYNC_3x_h1x; + lines_out = {1'b0, lines_3x_h1x}; + linebuf_rdclock = pclk_3x_h5x; + linebuf_hoffset = hcnt_3x_h5x; + pclk_act = pclk_3x_h5x; + hcnt_act = hcnt_3x_h5x; + vcnt_act = vcnt_3x_h1x/2'h3; //divider generated + slid_act = (vcnt_3x_h1x % 2'h3); + end + endcase + end + default: begin + R_act = 0; + G_act = 0; + B_act = 0; + DATA_enable_act = 0; + PCLK_out = 0; + HSYNC_act = 0; + VSYNC_act = VSYNC_1x; + lines_out = 0; + linebuf_rdclock = 0; + linebuf_hoffset = 0; + pclk_act = 0; + slid_act = 0; + hcnt_act = 0; + vcnt_act = 0; + end + endcase +end + +pll_2x pll_linedouble ( + .areset ( (H_LINEMULT != `LINEMULT_DOUBLE) ), + .inclk0 ( PCLK_in ), + .c0 ( pclk_2x ), + .locked ( pclk_2x_lock ) +); + +pll_3x pll_linetriple ( + .areset ( ((H_LINEMULT != `LINEMULT_TRIPLE) | H_L3MODE[1]) ), + .inclk0 ( PCLK_in ), + .c0 ( pclk_3x ), // sampling clock for 240p: 1280 or 960 samples & MODE0: 1280 output pixels from 1280 input samples (16:9) + .c1 ( pclk_4x ), // MODE1: 1280 output pixels from 960 input samples (960 drawn -> 4:3 aspect) + .locked ( pclk_3x_lock ) +); + +pll_3x_lowfreq pll_linetriple_lowfreq ( + .areset ( (H_LINEMULT != `LINEMULT_TRIPLE) | ~H_L3MODE[1]), + .inclk0 ( PCLK_in ), + .c0 ( pclk_3x_h1x ), // sampling clock for 240p: 320 or 256 samples + .c1 ( pclk_3x_h4x ), // MODE2: 1280 output pixels from 320 input samples (960 drawn -> 4:3 aspect) + .c2 ( pclk_3x_h5x ), // MODE3: 1280 output pixels from 256 input samples (1024 drawn -> 5:4 aspect) + .locked ( pclk_3x_lowfreq_lock ) +); + +//TODO: add secondary buffers for interlaced signals with alternative field order +linebuf linebuf_rgb ( + .data ( {R_1x, G_1x, B_1x} ), //or *_in? + .rdaddress ( linebuf_hoffset + (~line_idx << 11) ), + .rdclock ( linebuf_rdclock ), + .wraddress ( hcnt_1x + (line_idx << 11) ), + .wrclock ( pclk_1x ), + .wren ( 1'b1 ), + .q ( {R_lbuf, G_lbuf, B_lbuf} ) +); + +//Postprocess pipeline +always @(posedge pclk_act /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + R_pp1 <= apply_mask(1, R_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); + G_pp1 <= apply_mask(1, G_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); + B_pp1 <= apply_mask(1, B_act, hcnt_act, H_BACKPORCH+H_MASK, H_BACKPORCH+H_ACTIVE-H_MASK, vcnt_act, V_BACKPORCH+V_MASK, V_BACKPORCH+V_ACTIVE-V_MASK); + HSYNC_pp1 <= HSYNC_act; + VSYNC_pp1 <= VSYNC_act; + DATA_enable_pp1 <= DATA_enable_act; + + R_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, R_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); + G_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, G_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); + B_out <= apply_scanlines(V_SCANLINES, V_SCANLINEDIR, B_pp1, V_SCANLINESTR, {1'b0, V_SCANLINEID}, slid_act, hcnt_act[0]); + HSYNC_out <= HSYNC_pp1; + VSYNC_out <= VSYNC_pp1; + DATA_enable <= DATA_enable_pp1; + end +end + +//Generate a warning signal from horizontal instability or PLL sync loss +always @(posedge pclk_1x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + if (hmax[0] != hmax[1]) + warn_h_unstable <= 1; + else if (warn_h_unstable != 0) + warn_h_unstable <= warn_h_unstable + 1'b1; + + if ((H_LINEMULT == `LINEMULT_DOUBLE) & ~pclk_2x_lock) + warn_pll_lock_lost <= 1; + else if (warn_pll_lock_lost != 0) + warn_pll_lock_lost <= warn_pll_lock_lost + 1'b1; + + if ((H_LINEMULT == `LINEMULT_TRIPLE) & ~H_L3MODE[1] & ~pclk_3x_lock) + warn_pll_lock_lost_3x <= 1; + else if (warn_pll_lock_lost_3x != 0) + warn_pll_lock_lost_3x <= warn_pll_lock_lost_3x + 1'b1; + + if ((H_LINEMULT == `LINEMULT_TRIPLE) & H_L3MODE[1] & ~pclk_3x_lowfreq_lock) + warn_pll_lock_lost_3x_lowfreq <= 1; + else if (warn_pll_lock_lost_3x_lowfreq != 0) + warn_pll_lock_lost_3x_lowfreq <= warn_pll_lock_lost_3x_lowfreq + 1'b1; + end +end + +assign h_unstable = (warn_h_unstable != 0); +assign pll_lock_lost = {(warn_pll_lock_lost != 0), (warn_pll_lock_lost_3x != 0), (warn_pll_lock_lost_3x_lowfreq != 0)}; + +//Buffer the inputs using input pixel clock and generate 1x signals +always @(posedge pclk_1x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + if (`HSYNC_TRAILING_EDGE) + begin + hcnt_1x <= 0; + hmax[line_idx] <= hcnt_1x; + line_idx <= line_idx ^ 1'b1; + vcnt_1x <= vcnt_1x + 1'b1; + vcnt_1x_tvp <= vcnt_1x_tvp + 1'b1; + end + else + begin + hcnt_1x <= hcnt_1x + 1'b1; + end + + if (`VSYNC_TRAILING_EDGE) //should be checked at every pclk_1x? + begin + vcnt_1x_tvp <= 0; + FID_prev <= FID_in; + + // detect non-interlaced signal with odd-odd field signaling (TVP7002 detects it as interlaced with analog sync inputs). + // FID is updated at leading edge of VSYNC, so trailing edge has the status of current field. + if (FID_in == FID_prev) + fpga_vsyncgen[`VSYNCGEN_CHOPMID_BIT] <= `FALSE; + else if (FID_in == `FID_ODD) // TVP7002 falsely indicates field change with (vcnt < active_lines) + fpga_vsyncgen[`VSYNCGEN_CHOPMID_BIT] <= (vcnt_1x_tvp < `MIN_VALID_LINES); + + if (!(`FALSE_FIELD)) + begin + vcnt_1x <= 0; + lines_1x <= vcnt_1x; + end + + //Read configuration data from CPU + H_ACTIVE <= h_info[26:16]; // Horizontal active length from by the CPU - 11bits (0...2047) + H_BACKPORCH <= h_info[7:0]; // Horizontal backporch length from by the CPU - 8bits (0...255) + H_LINEMULT <= h_info[31:30]; // Horizontal line multiply mode + H_L3MODE <= h_info[29:28]; // Horizontal line triple mode + H_MASK <= {h_info[11:8], 2'b00}; + V_ACTIVE <= v_info[23:13]; // Vertical active length from by the CPU, 11bits (0...2047) + V_BACKPORCH <= v_info[5:0]; // Vertical backporch length from by the CPU, 6bits (0...64) + V_SCANLINES <= v_info[29]; + V_SCANLINEDIR <= v_info[28]; + V_SCANLINEID <= v_info[27]; + V_SCANLINESTR <= ((v_info[26:24]+8'h01)<<5)-1'b1; + V_MASK <= {v_info[9:6], 2'b00}; + end + + prev_hs <= HSYNC_in; + prev_vs <= VSYNC_in; + + // record start position of HSYNC + if (`HSYNC_LEADING_EDGE) + HSYNC_start <= hcnt_1x; + + R_1x <= R_in; + G_1x <= G_in; + B_1x <= B_in; + HSYNC_1x <= HSYNC_in; + + // Ignore possible invalid vsyncs generated by TVP7002 + if (vcnt_1x > V_ACTIVE) + VSYNC_1x <= VSYNC_in; + + // Check if extra vsync needed + fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] <= (lines_1x > ({1'b0, V_ACTIVE} << 1)) ? 1'b1 : 1'b0; + + h_enable_1x <= ((hcnt_1x >= H_BACKPORCH) & (hcnt_1x < H_BACKPORCH + H_ACTIVE)); + v_enable_1x <= ((vcnt_1x >= V_BACKPORCH) & (vcnt_1x < V_BACKPORCH + V_ACTIVE)); //- FID_in ??? + + /*HSYNC_out_debug <= HSYNC_in; + VSYNC_out_debug <= VSYNC_in;*/ + end +end + +//Generate 2x signals for linedouble +always @(posedge pclk_2x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + if ((pclk_1x == 1'b0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x + hcnt_2x <= 0; + else if (hcnt_2x == hmax[~line_idx]) //line_idx_prev? + hcnt_2x <= 0; + else + hcnt_2x <= hcnt_2x + 1'b1; + + if (hcnt_2x == 0) + vcnt_2x <= vcnt_2x + 1'b1; + + if ((pclk_1x == 1'b0) & (fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] == 1'b1)) + begin + if (`VSYNC_TRAILING_EDGE) + vcnt_2x <= 0; + else if (vcnt_2x == lines_1x) + begin + vcnt_2x <= 0; + lines_2x <= vcnt_2x; + end + end + else if ((pclk_1x == 1'b0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x + begin + vcnt_2x <= 0; + lines_2x <= vcnt_2x; + end + + if (pclk_1x == 1'b0) + begin + if (fpga_vsyncgen[`VSYNCGEN_GENMID_BIT] == 1'b1) + VSYNC_2x <= (vcnt_2x >= lines_1x - `VSYNCGEN_LEN) ? 1'b0 : 1'b1; + else if (vcnt_1x > V_ACTIVE) + VSYNC_2x <= VSYNC_in; + end + + HSYNC_2x <= ~(hcnt_2x >= HSYNC_start); + //TODO: VSYNC_2x + h_enable_2x <= ((hcnt_2x >= H_BACKPORCH) & (hcnt_2x < H_BACKPORCH + H_ACTIVE)); + v_enable_2x <= ((vcnt_2x >= (V_BACKPORCH<<1)) & (vcnt_2x < ((V_BACKPORCH + V_ACTIVE)<<1))); + end +end + +//Generate 3x signals for linetriple M0 +always @(posedge pclk_3x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + if ((pclk_3x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x + hcnt_3x <= 0; + else if (hcnt_3x == hmax[~line_idx]) //line_idx_prev? + hcnt_3x <= 0; + else + hcnt_3x <= hcnt_3x + 1'b1; + + if (hcnt_3x == 0) + vcnt_3x <= vcnt_3x + 1'b1; + + if ((pclk_3x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x + begin + vcnt_3x <= 0; + lines_3x <= vcnt_3x; + end + + HSYNC_3x <= ~(hcnt_3x >= HSYNC_start); + //TODO: VSYNC_3x + h_enable_3x <= ((hcnt_3x >= H_BACKPORCH) & (hcnt_3x < H_BACKPORCH + H_ACTIVE)); + v_enable_3x <= ((vcnt_3x >= (3*V_BACKPORCH)) & (vcnt_3x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!! + + //read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg) + if (((pclk_1x_prev3x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_cnt == 2'h2)) + pclk_3x_cnt <= 0; + else + pclk_3x_cnt <= pclk_3x_cnt + 1'b1; + + pclk_1x_prev3x <= pclk_1x; + end +end + +//Generate 4x signals for linetriple M1 +always @(posedge pclk_4x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + // Can we sync reliably to h_enable_3x??? + if ((h_enable_3x == 1) & (h_enable_3x_prev4x == 0)) + hcnt_4x <= hcnt_3x - 160; + else + hcnt_4x <= hcnt_4x + 1'b1; + + h_enable_3x_prev4x <= h_enable_3x; + end +end + + + +//Generate 3x_h1x signals for linetriple M2 and M3 +always @(posedge pclk_3x_h1x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + if ((pclk_3x_h1x_cnt == 0) & `HSYNC_TRAILING_EDGE) //sync with posedge of pclk_1x + hcnt_3x_h1x <= 0; + else if (hcnt_3x_h1x == hmax[~line_idx]) //line_idx_prev? + hcnt_3x_h1x <= 0; + else + hcnt_3x_h1x <= hcnt_3x_h1x + 1'b1; + + if (hcnt_3x_h1x == 0) + vcnt_3x_h1x <= vcnt_3x_h1x + 1'b1; + + if ((pclk_3x_h1x_cnt == 0) & `VSYNC_TRAILING_EDGE & !(`FALSE_FIELD)) //sync with posedge of pclk_1x + begin + vcnt_3x_h1x <= 0; + lines_3x_h1x <= vcnt_3x_h1x; + end + + HSYNC_3x_h1x <= ~(hcnt_3x_h1x >= HSYNC_start); + //TODO: VSYNC_3x_h1x + h_enable_3x_h1x <= ((hcnt_3x_h1x >= H_BACKPORCH) & (hcnt_3x_h1x < H_BACKPORCH + H_ACTIVE)); + v_enable_3x_h1x <= ((vcnt_3x_h1x >= (3*V_BACKPORCH)) & (vcnt_3x_h1x < (3*(V_BACKPORCH + V_ACTIVE)))); //multiplier generated!!! + + //read pclk_1x to examine when edges are synced (pclk_1x=1 @ 120deg & pclk_1x=0 @ 240deg) + if (((pclk_1x_prev3x_h1x == 1'b1) & (pclk_1x == 1'b0)) | (pclk_3x_h1x_cnt == 2'h2)) + pclk_3x_h1x_cnt <= 0; + else + pclk_3x_h1x_cnt <= pclk_3x_h1x_cnt + 1'b1; + + pclk_1x_prev3x_h1x <= pclk_1x; + end +end + + + +//Generate 3x_h4x signals for for linetriple M2 +always @(posedge pclk_3x_h4x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + // Can we sync reliably to h_enable_3x??? + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0)) + hcnt_3x_h4x <= hcnt_3x_h1x - (160/3); + else if (hcnt_3x_h4x_ctr == 2'h0) + hcnt_3x_h4x <= hcnt_3x_h4x + 1'b1; + + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h4x == 0)) + hcnt_3x_h4x_ctr <= 2'h1; + else if (hcnt_3x_h4x_ctr == 2'h2) + hcnt_3x_h4x_ctr <= 2'h0; + else + hcnt_3x_h4x_ctr <= hcnt_3x_h4x_ctr + 1'b1; + + h_enable_3x_prev3x_h4x <= h_enable_3x_h1x; + end +end + +//Generate 3x_h5x signals for for linetriple M3 +always @(posedge pclk_3x_h5x /*or negedge reset_n*/) +begin + /*if (!reset_n) + begin + end + else*/ + begin + // Can we sync reliably to h_enable_3x??? + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0)) + hcnt_3x_h5x <= hcnt_3x_h1x - (128/4); + else if (hcnt_3x_h5x_ctr == 2'h0) + hcnt_3x_h5x <= hcnt_3x_h5x + 1'b1; + + if ((h_enable_3x_h1x == 1) & (h_enable_3x_prev3x_h5x == 0)) + hcnt_3x_h5x_ctr <= 2'h2; + else + hcnt_3x_h5x_ctr <= hcnt_3x_h5x_ctr + 1'b1; + + h_enable_3x_prev3x_h5x <= h_enable_3x_h1x; + end +end + +endmodule diff --git a/rtl/timescale.v b/rtl/timescale.v new file mode 100644 index 0000000..60d4ecb --- /dev/null +++ b/rtl/timescale.v @@ -0,0 +1,2 @@ +`timescale 1ns / 10ps + diff --git a/rtl/videogen.v b/rtl/videogen.v new file mode 100644 index 0000000..3e44597 --- /dev/null +++ b/rtl/videogen.v @@ -0,0 +1,150 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +module videogen ( + input clk27, + input reset_n, + output [7:0] R_out, + output [7:0] G_out, + output [7:0] B_out, + output reg HSYNC_out, + output reg VSYNC_out, + output PCLK_out, + output reg ENABLE_out +); + +//Parameters for 720x480@60Hz (858dots x 525lines), dotclk 27MHz -> 59.94Hz +parameter H_SYNCLEN = 62; +parameter H_BACKPORCH = 60; +parameter H_ACTIVE = 720; +parameter H_FRONTPORCH = 16; +parameter H_TOTAL = 858; + +parameter V_SYNCLEN = 6; +parameter V_BACKPORCH = 30; +parameter V_ACTIVE = 480; +parameter V_FRONTPORCH = 9; +parameter V_TOTAL = 525; + +parameter H_OVERSCAN = 40; //at both sides +parameter V_OVERSCAN = 16; //top and bottom +parameter H_AREA = 640; +parameter V_AREA = 448; +parameter H_BORDER = (H_AREA-512)/2; +parameter V_BORDER = (V_AREA-256)/2; + +parameter X_START = H_SYNCLEN + H_BACKPORCH; +parameter Y_START = V_SYNCLEN + V_BACKPORCH; + +//Counters +reg [9:0] h_cnt; //max. 1024 +reg [9:0] v_cnt; //max. 1024 + +reg [9:0] xpos; +reg [9:0] ypos; + +assign PCLK_out = clk27; + +//R, G and B should be 0 outside of active area +assign R_out = ENABLE_out ? V_gen : 8'h00; +assign G_out = ENABLE_out ? V_gen : 8'h00; +assign B_out = ENABLE_out ? V_gen : 8'h00; + +reg [7:0] V_gen; + + +//HSYNC gen (negative polarity) +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + h_cnt <= 0; + HSYNC_out <= 0; + end + else + begin + //Hsync counter + if (h_cnt < H_TOTAL-1 ) + h_cnt <= h_cnt + 1; + else + h_cnt <= 0; + + //Hsync signal + HSYNC_out <= (h_cnt < H_SYNCLEN) ? 0 : 1; + end +end + +//VSYNC gen (negative polarity) +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + v_cnt <= 0; + VSYNC_out <= 0; + end + else + begin + if (h_cnt == 0) + begin + //Vsync counter + if (v_cnt < V_TOTAL-1 ) + v_cnt <= v_cnt + 1; + else + v_cnt <= 0; + + //Vsync signal + VSYNC_out <= (v_cnt < V_SYNCLEN) ? 0 : 1; + end + end +end + +//Data gen +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + V_gen <= 8'h00; + end + else + begin + if ((h_cnt < X_START+H_OVERSCAN) || (h_cnt >= X_START+H_OVERSCAN+H_AREA) || (v_cnt < Y_START+V_OVERSCAN) || (v_cnt >= Y_START+V_OVERSCAN+V_AREA)) + V_gen <= (h_cnt[0] ^ v_cnt[0]) ? 8'hff : 8'h00; + else if ((h_cnt < X_START+H_OVERSCAN+H_BORDER) || (h_cnt >= X_START+H_OVERSCAN+H_AREA-H_BORDER) || (v_cnt < Y_START+V_OVERSCAN+V_BORDER) || (v_cnt >= Y_START+V_OVERSCAN+V_AREA-V_BORDER)) + V_gen <= 8'h50; + else + V_gen <= (h_cnt - (X_START+H_OVERSCAN+H_BORDER)) >> 1; + /*else + V_gen <= 8'h00;*/ + end +end + +//Enable gen +always @(posedge clk27 or negedge reset_n) +begin + if (!reset_n) + begin + ENABLE_out <= 8'h00; + end + else + begin + ENABLE_out <= (h_cnt >= X_START && h_cnt < X_START + H_ACTIVE && v_cnt >= Y_START && v_cnt < Y_START + V_ACTIVE); + end +end + +endmodule diff --git a/software/sys_controller/Makefile b/software/sys_controller/Makefile new file mode 100644 index 0000000..66e5d99 --- /dev/null +++ b/software/sys_controller/Makefile @@ -0,0 +1,1099 @@ +#------------------------------------------------------------------------------ +# VARIABLES APPENDED TO BY INCLUDED MAKEFILE FRAGMENTS +#------------------------------------------------------------------------------ + +# List of include directories for -I compiler option (-I added when used). +# Includes the BSP. +ALT_INCLUDE_DIRS := + +# List of library directories for -L linker option (-L added when used). +# Includes the BSP. +ALT_LIBRARY_DIRS := + +# List of library names for -l linker option (-l added when used). +# Includes the BSP. +ALT_LIBRARY_NAMES := + +# List of library names for -msys-lib linker option (-msys-lib added when used). +# These are libraries that might be located in the BSP and depend on the BSP +# library, or vice versa +ALT_BSP_DEP_LIBRARY_NAMES := + +# List of dependencies for the linker. This is usually the full pathname +# of each library (*.a) file. +# Includes the BSP. +ALT_LDDEPS := + +# List of root library directories that support running make to build them. +# Includes the BSP and any ALT libraries. +MAKEABLE_LIBRARY_ROOT_DIRS := + +# Generic flags passed to the compiler for different types of input files. +ALT_CFLAGS := +ALT_CXXFLAGS := +ALT_CPPFLAGS := +ALT_ASFLAGS := +ALT_LDFLAGS := + + +#------------------------------------------------------------------------------ +# The adjust-path macro +# +# If COMSPEC/ComSpec is defined, Make is launched from Windows through +# Cygwin. The adjust-path macro converts absolute windows paths into +# unix style paths (Example: c:/dir -> /c/dir). This will ensture +# paths are readable by GNU Make. +# +# If COMSPEC/ComSpec is not defined, Make is launched from linux, and no +# adjustment is necessary +# +#------------------------------------------------------------------------------ + +ifndef COMSPEC +ifdef ComSpec +COMSPEC = $(ComSpec) +endif # ComSpec +endif # COMSPEC + +ifdef COMSPEC # if Windows OS + +ifeq ($(MAKE_VERSION),3.81) +# +# adjust-path/adjust-path-mixed for Mingw Gnu Make on Windows +# +# Example Usage: +# $(call adjust-path,c:/aaa/bbb) => /c/aaa/bbb +# $(call adjust-path-mixed,/c/aaa/bbb) => c:/aaa/bbb +# $(call adjust-path-mixed,/cygdrive/c/aaa/bbb) => c:/aaa/bbb +# + +# +# adjust-path +# - converts back slash characters into forward slashes +# - if input arg ($1) is an empty string then return the empty string +# - if input arg ($1) does not contain the string ":/", then return input arg +# - using sed, convert mixed path [c:/...] into mingw path [/c/...] +define adjust-path +$(strip \ +$(if $1,\ +$(if $(findstring :/,$(subst \,/,$1)),\ +$(shell echo $(subst \,/,$1) | sed -e 's,^\([a-zA-Z]\):/,/\1/,'),\ +$(subst \,/,$1)))) +endef + +# +# adjust-path-mixed +# - converts back slash characters into forward slashes +# - if input arg ($1) is an empty string then return the empty string +# - if input arg ($1) does not begin with a forward slash '/' char, then +# return input arg +# - using sed, convert mingw path [/c/...] or cygwin path [/c/cygdrive/...] +# into a mixed path [c:/...] +define adjust-path-mixed +$(strip \ +$(if $1,\ +$(if $(findstring $(subst \,/,$1),$(patsubst /%,%,$(subst \,/,$1))),\ +$(subst \,/,$1),\ +$(shell echo $(subst \,/,$1) | sed -e 's,^/cygdrive/\([a-zA-Z]\)/,\1:/,' -e 's,^/\([a-zA-Z]\)/,\1:/,')))) +endef + +else # MAKE_VERSION != 3.81 (MAKE_VERSION == 3.80 or MAKE_VERSION == 3.79) +# +# adjust-path for Cygwin Gnu Make +# $(call adjust-path,c:/aaa/bbb) = /cygdrive/c/aaa/bbb +# $(call adjust-path-mixed,/cygdrive/c/aaa/bbb) = c:/aaa/bbb +# +adjust-path = $(if $1,$(shell cygpath -u "$1"),) +adjust-path-mixed = $(if $1,$(shell cygpath -m "$1"),) +endif + +else # !COMSPEC + +adjust-path = $1 +adjust-path-mixed = $1 + +endif # COMSPEC + + +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# GENERATED SETTINGS START v +#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +#START GENERATED +ACTIVE_BUILD_CONFIG := default +BUILD_CONFIGS := default + +# The following TYPE comment allows tools to identify the 'type' of target this +# makefile is associated with. +# TYPE: APP_MAKEFILE + +# This following VERSION comment indicates the version of the tool used to +# generate this makefile. A makefile variable is provided for VERSION as well. +# ACDS_VERSION: 14.1 +ACDS_VERSION := 14.1 + +# This following BUILD_NUMBER comment indicates the build number of the tool +# used to generate this makefile. +# BUILD_NUMBER: 190 + +# Define path to the application ELF. +# It may be used by the makefile fragments so is defined before including them. +# +ELF := sys_controller.elf + +# Paths to C, C++, and assembly source files. +C_SRCS += av_controller.c +C_SRCS += it6613/EDID.c +C_SRCS += it6613/HDMI_TX.c +C_SRCS += it6613/hdmitx_nios2.c +C_SRCS += it6613/it6613.c +C_SRCS += it6613/it6613_drv.c +C_SRCS += it6613/it6613_sys.c +C_SRCS += tvp7002/tvp7002.c +C_SRCS += tvp7002/video_modes.c +C_SRCS += ths7353/ths7353.c +C_SRCS += spi_charlcd/lcd.c +CXX_SRCS := +ASM_SRCS := + + +# Path to root of object file tree. +OBJ_ROOT_DIR := obj + +# Options to control objdump. +CREATE_OBJDUMP := 1 +OBJDUMP_INCLUDE_SOURCE := 1 +OBJDUMP_FULL_CONTENTS := 0 + +# Options to enable/disable optional files. +CREATE_ELF_DERIVED_FILES := 0 +CREATE_LINKER_MAP := 1 + +# Common arguments for ALT_CFLAGSs +APP_CFLAGS_DEFINED_SYMBOLS := -DNO_I2C_DEBUG -DNO_DEBUG +APP_CFLAGS_UNDEFINED_SYMBOLS := +APP_CFLAGS_OPTIMIZATION := -Os +APP_CFLAGS_DEBUG_LEVEL := +APP_CFLAGS_WARNINGS := -Wall +APP_CFLAGS_USER_FLAGS := -fdata-sections -ffunction-sections -fshort-enums + +APP_ASFLAGS_USER := +APP_LDFLAGS_USER := -Wl,--gc-sections + +# Linker options that have default values assigned later if not +# assigned here. +LINKER_SCRIPT := +CRT0 := +SYS_LIB := + +# Define path to the root of the BSP. +BSP_ROOT_DIR := ../sys_controller_bsp/ + +# List of application specific include directories, library directories and library names +APP_INCLUDE_DIRS += it6613 +APP_INCLUDE_DIRS += tvp7002 +APP_INCLUDE_DIRS += ./ +APP_INCLUDE_DIRS += ths7353 +APP_INCLUDE_DIRS += spi_charlcd +APP_LIBRARY_DIRS := +APP_LIBRARY_NAMES := + +# Pre- and post- processor settings. +BUILD_PRE_PROCESS := +BUILD_POST_PROCESS := + +QUARTUS_PROJECT_DIR := ../../ + + +#END GENERATED + +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# GENERATED SETTINGS END ^ +#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +#------------------------------------------------------------------------------ +# DEFAULT TARGET +#------------------------------------------------------------------------------ + +# Define the variable used to echo output if not already defined. +ifeq ($(ECHO),) +ECHO := echo +endif + +# Put "all" rule before included makefile fragments because they may +# define rules and we don't want one of those to become the default rule. +.PHONY : all + +all: + @$(ECHO) [$(APP_NAME) build complete] + +all : build_pre_process libs app build_post_process + + +#------------------------------------------------------------------------------ +# VARIABLES DEPENDENT ON GENERATED CONTENT +#------------------------------------------------------------------------------ + +# Define object file directory per build configuration +CONFIG_OBJ_DIR := $(OBJ_ROOT_DIR)/$(ACTIVE_BUILD_CONFIG) + +ifeq ($(BSP_ROOT_DIR),) +$(error Edit Makefile and provide a value for BSP_ROOT_DIR) +endif + +ifeq ($(wildcard $(BSP_ROOT_DIR)),) +$(error BSP directory does not exist: $(BSP_ROOT_DIR)) +endif + +# Define absolute path to the root of the BSP. +ABS_BSP_ROOT_DIR := $(call adjust-path-mixed,$(shell cd "$(BSP_ROOT_DIR)"; pwd)) + +# Include makefile fragments. Define variable ALT_LIBRARY_ROOT_DIR before +# including each makefile fragment so that it knows the path to itself. +BSP_INCLUDE_FILE := $(BSP_ROOT_DIR)/public.mk +ALT_LIBRARY_ROOT_DIR := $(BSP_ROOT_DIR) +include $(BSP_INCLUDE_FILE) +# C2H will need this to touch the BSP public.mk and avoid the sopc file +# out-of-date error during a BSP make +ABS_BSP_INCLUDE_FILE := $(ABS_BSP_ROOT_DIR)/public.mk + + +ifneq ($(WARNING.SMALL_STACK_SIZE),) +# This WARNING is here to protect you from unknowingly using a very small stack +# If the warning is set, increase your stack size or enable the BSP small stack +# setting to eliminate the warning +$(warning WARNING: $(WARNING.SMALL_STACK_SIZE)) +endif + +# If the BSP public.mk indicates that ALT_SIM_OPTIMIZE is set, rename the ELF +# by prefixing it with RUN_ON_HDL_SIMULATOR_ONLY_. +ifneq ($(filter -DALT_SIM_OPTIMIZE,$(ALT_CPPFLAGS)),) +ELF := RUN_ON_HDL_SIMULATOR_ONLY_$(ELF) +endif + +# If the BSP public.mk indicates that ALT_PROVIDE_GMON is set, add option to +# download_elf target +ifneq ($(filter -DALT_PROVIDE_GMON,$(ALT_CPPFLAGS)),) +GMON_OUT_FILENAME := gmon.out +WRITE_GMON_OPTION := --write-gmon $(GMON_OUT_FILENAME) +endif + +# Name of ELF application. +APP_NAME := $(basename $(ELF)) + +# Set to defaults if variables not already defined in settings. +ifeq ($(LINKER_SCRIPT),) +LINKER_SCRIPT := $(BSP_LINKER_SCRIPT) +endif +ifeq ($(CRT0),) +CRT0 := $(BSP_CRT0) +endif +ifeq ($(SYS_LIB),) +SYS_LIB := $(BSP_SYS_LIB) +endif + +OBJDUMP_NAME := $(APP_NAME).objdump +OBJDUMP_FLAGS := --disassemble --syms --all-header +ifeq ($(OBJDUMP_INCLUDE_SOURCE),1) +OBJDUMP_FLAGS += --source +endif +ifeq ($(OBJDUMP_FULL_CONTENTS),1) +OBJDUMP_FLAGS += --full-contents +endif + +# Create list of linker dependencies (*.a files). +APP_LDDEPS := $(ALT_LDDEPS) $(LDDEPS) + +# Take lists and add required prefixes. +APP_INC_DIRS := $(addprefix -I, $(ALT_INCLUDE_DIRS) $(APP_INCLUDE_DIRS) $(INC_DIRS)) +ASM_INC_PREFIX := -Wa,-I +APP_ASM_INC_DIRS := $(addprefix $(ASM_INC_PREFIX), $(ALT_INCLUDE_DIRS) $(APP_INCLUDE_DIRS) $(INC_DIRS)) +APP_LIB_DIRS := $(addprefix -L, $(ALT_LIBRARY_DIRS) $(APP_LIBRARY_DIRS) $(LIB_DIRS)) +APP_LIBS := $(addprefix -l, $(ALT_LIBRARY_NAMES) $(APP_LIBRARY_NAMES) $(LIBS)) + +ifneq ($(AVOID_NIOS2_GCC3_OPTIONS),) + +# +# Avoid Nios II GCC 3.X options. +# + +# Detect if small newlib C library is requested. +# If yes, remove the -msmallc option because it is +# now handled by other means. +ifneq ($(filter -msmallc,$(ALT_LDFLAGS)),) + ALT_LDFLAGS := $(filter-out -msmallc,$(ALT_LDFLAGS)) + ALT_C_LIBRARY := smallc +else + ALT_C_LIBRARY := c +endif + +# Put each BSP dependent library in a group to avoid circular dependencies. +APP_BSP_DEP_LIBS := $(foreach l,$(ALT_BSP_DEP_LIBRARY_NAMES),-Wl,--start-group -l$(ALT_C_LIBRARY) -lgcc -l$(l) -Wl,--end-group) + +else # !AVOID_NIOS2_GCC3_OPTIONS + +# +# Use Nios II GCC 3.X options. +# +APP_BSP_DEP_LIBS := $(addprefix -msys-lib=, $(ALT_BSP_DEP_LIBRARY_NAMES)) + +endif # !AVOID_NIOS2_GCC3_OPTIONS + +# Arguments for the C preprocessor, C/C++ compiler, assembler, and linker. +APP_CFLAGS := $(APP_CFLAGS_DEFINED_SYMBOLS) \ + $(APP_CFLAGS_UNDEFINED_SYMBOLS) \ + $(APP_CFLAGS_OPTIMIZATION) \ + $(APP_CFLAGS_DEBUG_LEVEL) \ + $(APP_CFLAGS_WARNINGS) \ + $(APP_CFLAGS_USER_FLAGS) \ + $(ALT_CFLAGS) \ + $(CFLAGS) + +# Arguments only for the C++ compiler. +APP_CXXFLAGS := $(ALT_CXXFLAGS) $(CXXFLAGS) + +# Arguments only for the C preprocessor. +# Prefix each include directory with -I. +APP_CPPFLAGS := $(APP_INC_DIRS) \ + $(ALT_CPPFLAGS) \ + $(CPPFLAGS) + +# Arguments only for the assembler. +APP_ASFLAGS := $(APP_ASM_INC_DIRS) \ + $(ALT_ASFLAGS) \ + $(APP_ASFLAGS_USER) \ + $(ASFLAGS) + +# Arguments only for the linker. +APP_LDFLAGS := $(APP_LDFLAGS_USER) + +ifneq ($(LINKER_SCRIPT),) +APP_LDFLAGS += -T'$(LINKER_SCRIPT)' +endif + +ifneq ($(AVOID_NIOS2_GCC3_OPTIONS),) + +# Avoid Nios II GCC 3.x options. +ifneq ($(CRT0),) +APP_LDFLAGS += $(CRT0) +endif + +# The equivalent of the -msys-lib option is provided +# by the GROUP() command in the linker script. +# Note this means the SYS_LIB variable is now ignored. + +else # !AVOID_NIOS2_GCC3_OPTIONS + +# Use Nios II GCC 3.x options. +ifneq ($(CRT0),) +APP_LDFLAGS += -msys-crt0='$(CRT0)' +endif +ifneq ($(SYS_LIB),) +APP_LDFLAGS += -msys-lib=$(SYS_LIB) +endif + +endif # !AVOID_NIOS2_GCC3_OPTIONS + +APP_LDFLAGS += \ + $(APP_LIB_DIRS) \ + $(ALT_LDFLAGS) \ + $(LDFLAGS) + +LINKER_MAP_NAME := $(APP_NAME).map +ifeq ($(CREATE_LINKER_MAP), 1) +APP_LDFLAGS += -Wl,-Map=$(LINKER_MAP_NAME) +endif + +# QUARTUS_PROJECT_DIR and SOPC_NAME need to be defined if you want the +# mem_init_install target of the mem_init.mk (located in the associated BSP) +# to know how to copy memory initialization files (e.g. .dat, .hex) into +# directories required for Quartus compilation or RTL simulation. + +# Defining QUARTUS_PROJECT_DIR causes mem_init_install to copy memory +# initialization files into your Quartus project directory. This is required +# to provide the initial memory contents of FPGA memories that can be +# initialized by the programming file (.sof) or Hardcopy ROMs. It is also used +# for VHDL simulation of on-chip memories. + +# Defining SOPC_NAME causes the mem_init_install target to copy memory +# initialization files into your RTL simulation directory. This is required +# to provide the initial memory contents of all memories that can be +# initialized by RTL simulation. This variable should be set to the same name +# as your SOPC Builder system name. For example, if you have a system called +# "foo.sopc", this variable should be set to "foo". + +# If SOPC_NAME is not set and QUARTUS_PROJECT_DIR is set, then derive SOPC_NAME. +ifeq ($(SOPC_NAME),) +ifneq ($(QUARTUS_PROJECT_DIR),) +SOPC_NAME := $(basename $(notdir $(wildcard $(QUARTUS_PROJECT_DIR)/*.sopcinfo))) +endif +endif + +# Defining JDI_FILE is required to specify the JTAG Debug Information File +# path. This file is generated by Quartus, and is needed along with the +# .sopcinfo file to resolve processor instance ID's from names in a multi-CPU +# systems. For multi-CPU systems, the processor instance ID is used to select +# from multiple CPU's during ELF download. + +# Both JDI_FILE and SOPCINFO_FILE are provided by the BSP if they found during +# BSP creation. If JDI_FILE is not set and QUARTUS_PROJECT_DIR is set, then +# derive JDI_FILE. We do not attempt to derive SOPCINFO_FILE since there may be +# multiple .sopcinfo files in a Quartus project. +ifeq ($(JDI_FILE),) +ifneq ($(QUARTUS_PROJECT_DIR),) +JDI_FILE := $(firstword $(wildcard $(QUARTUS_PROJECT_DIR)/output_files/*.jdi) $(wildcard $(QUARTUS_PROJECT_DIR)/*.jdi)) +endif +endif + +# Path to root runtime directory used for hdl simulation +RUNTIME_ROOT_DIR := $(CONFIG_OBJ_DIR)/runtime + + + +#------------------------------------------------------------------------------ +# MAKEFILE INCLUDES DEPENDENT ON GENERATED CONTENT +#------------------------------------------------------------------------------ +# mem_init.mk is a generated makefile fragment. This file defines all targets +# used to generate HDL initialization simulation files and pre-initialized +# onchip memory files. +MEM_INIT_FILE := $(BSP_ROOT_DIR)/mem_init.mk +include $(MEM_INIT_FILE) + +# Create list of object files to be built using the list of source files. +# The source file hierarchy is preserved in the object tree. +# The supported file extensions are: +# +# .c - for C files +# .cxx .cc .cpp - for C++ files +# .S .s - for assembler files +# +# Handle source files specified by --src-dir & --src-rdir differently, to +# save some processing time in calling the adjust-path macro. + +OBJ_LIST_C := $(patsubst %.c,%.o,$(filter %.c,$(C_SRCS))) +OBJ_LIST_CPP := $(patsubst %.cpp,%.o,$(filter %.cpp,$(CXX_SRCS))) +OBJ_LIST_CXX := $(patsubst %.cxx,%.o,$(filter %.cxx,$(CXX_SRCS))) +OBJ_LIST_CC := $(patsubst %.cc,%.o,$(filter %.cc,$(CXX_SRCS))) +OBJ_LIST_S := $(patsubst %.S,%.o,$(filter %.S,$(ASM_SRCS))) +OBJ_LIST_SS := $(patsubst %.s,%.o,$(filter %.s,$(ASM_SRCS))) + +OBJ_LIST := $(sort $(OBJ_LIST_C) $(OBJ_LIST_CPP) $(OBJ_LIST_CXX) \ + $(OBJ_LIST_CC) $(OBJ_LIST_S) $(OBJ_LIST_SS)) + +SDIR_OBJ_LIST_C := $(patsubst %.c,%.o,$(filter %.c,$(SDIR_C_SRCS))) +SDIR_OBJ_LIST_CPP := $(patsubst %.cpp,%.o,$(filter %.cpp,$(SDIR_CXX_SRCS))) +SDIR_OBJ_LIST_CXX := $(patsubst %.cxx,%.o,$(filter %.cxx,$(SDIR_CXX_SRCS))) +SDIR_OBJ_LIST_CC := $(patsubst %.cc,%.o,$(filter %.cc,$(SDIR_CXX_SRCS))) +SDIR_OBJ_LIST_S := $(patsubst %.S,%.o,$(filter %.S,$(SDIR_ASM_SRCS))) +SDIR_OBJ_LIST_SS := $(patsubst %.s,%.o,$(filter %.s,$(SDIR_ASM_SRCS))) + +SDIR_OBJ_LIST := $(sort $(SDIR_OBJ_LIST_C) $(SDIR_OBJ_LIST_CPP) \ + $(SDIR_OBJ_LIST_CXX) $(SDIR_OBJ_LIST_CC) $(SDIR_OBJ_LIST_S) \ + $(SDIR_OBJ_LIST_SS)) + +# Relative-pathed objects that being with "../" are handled differently. +# +# Regular objects are created as +# $(CONFIG_OBJ_DIR)//.o +# where the path structure is maintained under the obj directory. This +# applies for both absolute and relative paths; in the absolute path +# case this means the entire source path will be recreated under the obj +# directory. This is done to allow two source files with the same name +# to be included as part of the project. +# +# Note: On Cygwin, the path recreated under the obj directory will be +# the cygpath -u output path. +# +# Relative-path objects that begin with "../" cause problems under this +# scheme, as $(CONFIG_OBJ_DIR)/..// can potentially put the object +# files anywhere in the system, creating clutter and polluting the source tree. +# As such, their paths are flattened - the object file created will be +# $(CONFIG_OBJ_DIR)/.o. Due to this, two files specified with +# "../" in the beginning cannot have the same name in the project. VPATH +# will be set for these sources to allow make to relocate the source file +# via %.o rules. +# +# The following lines separate the object list into the flatten and regular +# lists, and then handles them as appropriate. + +FLATTEN_OBJ_LIST := $(filter ../%,$(OBJ_LIST)) +FLATTEN_APP_OBJS := $(addprefix $(CONFIG_OBJ_DIR)/,$(notdir $(FLATTEN_OBJ_LIST))) + +REGULAR_OBJ_LIST := $(filter-out $(FLATTEN_OBJ_LIST),$(OBJ_LIST)) +REGULAR_OBJ_LIST_C := $(filter $(OBJ_LIST_C),$(REGULAR_OBJ_LIST)) +REGULAR_OBJ_LIST_CPP := $(filter $(OBJ_LIST_CPP),$(REGULAR_OBJ_LIST)) +REGULAR_OBJ_LIST_CXX := $(filter $(OBJ_LIST_CXX),$(REGULAR_OBJ_LIST)) +REGULAR_OBJ_LIST_CC := $(filter $(OBJ_LIST_CC),$(REGULAR_OBJ_LIST)) +REGULAR_OBJ_LIST_S := $(filter $(OBJ_LIST_S),$(REGULAR_OBJ_LIST)) +REGULAR_OBJ_LIST_SS := $(filter $(OBJ_LIST_SS),$(REGULAR_OBJ_LIST)) + +FLATTEN_SDIR_OBJ_LIST := $(filter ../%,$(SDIR_OBJ_LIST)) +FLATTEN_SDIR_APP_OBJS := $(addprefix $(CONFIG_OBJ_DIR)/,$(notdir $(FLATTEN_SDIR_OBJ_LIST))) + +REGULAR_SDIR_OBJ_LIST := $(filter-out $(FLATTEN_SDIR_OBJ_LIST),$(SDIR_OBJ_LIST)) +REGULAR_SDIR_OBJ_LIST_C := $(filter $(SDIR_OBJ_LIST_C),$(REGULAR_SDIR_OBJ_LIST)) +REGULAR_SDIR_OBJ_LIST_CPP := $(filter $(SDIR_OBJ_LIST_CPP),$(REGULAR_SDIR_OBJ_LIST)) +REGULAR_SDIR_OBJ_LIST_CXX := $(filter $(SDIR_OBJ_LIST_CXX),$(REGULAR_SDIR_OBJ_LIST)) +REGULAR_SDIR_OBJ_LIST_CC := $(filter $(SDIR_OBJ_LIST_CC),$(REGULAR_SDIR_OBJ_LIST)) +REGULAR_SDIR_OBJ_LIST_S := $(filter $(SDIR_OBJ_LIST_S),$(REGULAR_SDIR_OBJ_LIST)) +REGULAR_SDIR_OBJ_LIST_SS := $(filter $(SDIR_OBJ_LIST_SS),$(REGULAR_SDIR_OBJ_LIST)) + +VPATH := $(sort $(dir $(FLATTEN_OBJ_LIST)) $(dir $(FLATTEN_SDIR_OBJ_LIST))) + +APP_OBJS_C := $(addprefix $(CONFIG_OBJ_DIR)/,\ + $(REGULAR_SDIR_OBJ_LIST_C) \ + $(foreach s,$(REGULAR_OBJ_LIST_C),$(call adjust-path,$s))) + +APP_OBJS_CPP := $(addprefix $(CONFIG_OBJ_DIR)/,\ + $(REGULAR_SDIR_OBJ_LIST_CPP) \ + $(foreach s,$(REGULAR_OBJ_LIST_CPP),$(call adjust-path,$s))) + +APP_OBJS_CXX := $(addprefix $(CONFIG_OBJ_DIR)/,\ + $(REGULAR_SDIR_OBJ_LIST_CXX) \ + $(foreach s,$(REGULAR_OBJ_LIST_CXX),$(call adjust-path,$s))) + +APP_OBJS_CC := $(addprefix $(CONFIG_OBJ_DIR)/,\ + $(REGULAR_SDIR_OBJ_LIST_CC) \ + $(foreach s,$(REGULAR_OBJ_LIST_CC),$(call adjust-path,$s))) + +APP_OBJS_S := $(addprefix $(CONFIG_OBJ_DIR)/,\ + $(REGULAR_SDIR_OBJ_LIST_S) \ + $(foreach s,$(REGULAR_OBJ_LIST_S),$(call adjust-path,$s))) + +APP_OBJS_SS := $(addprefix $(CONFIG_OBJ_DIR)/,\ + $(REGULAR_SDIR_OBJ_LIST_SS) \ + $(foreach s,$(REGULAR_OBJ_LIST_SS),$(call adjust-path,$s))) + +APP_OBJS := $(APP_OBJS_C) $(APP_OBJS_CPP) $(APP_OBJS_CXX) $(APP_OBJS_CC) \ + $(APP_OBJS_S) $(APP_OBJS_SS) \ + $(FLATTEN_APP_OBJS) $(FLATTEN_SDIR_APP_OBJS) + +# Add any extra user-provided object files. +APP_OBJS += $(OBJS) + +# Create list of dependancy files for each object file. +APP_DEPS := $(APP_OBJS:.o=.d) + +# Patch the Elf file with system specific information + +# Patch the Elf with the name of the sopc system +ifneq ($(SOPC_NAME),) +ELF_PATCH_FLAG += --sopc_system_name $(SOPC_NAME) +endif + +# Patch the Elf with the absolute path to the Quartus Project Directory +ifneq ($(QUARTUS_PROJECT_DIR),) +ABS_QUARTUS_PROJECT_DIR := $(call adjust-path-mixed,$(shell cd "$(QUARTUS_PROJECT_DIR)"; pwd)) +ELF_PATCH_FLAG += --quartus_project_dir "$(ABS_QUARTUS_PROJECT_DIR)" +endif + +# Patch the Elf and download args with the JDI_FILE if specified +ifneq ($(wildcard $(JDI_FILE)),) +ELF_PATCH_FLAG += --jdi $(JDI_FILE) +DOWNLOAD_JDI_FLAG := --jdi $(JDI_FILE) +endif + +# Patch the Elf with the SOPCINFO_FILE if specified +ifneq ($(wildcard $(SOPCINFO_FILE)),) +ELF_PATCH_FLAG += --sopcinfo $(SOPCINFO_FILE) +endif + +# Use the DOWNLOAD_CABLE variable to specify which JTAG cable to use. +# This is not needed if you only have one cable. +ifneq ($(DOWNLOAD_CABLE),) +DOWNLOAD_CABLE_FLAG := --cable '$(DOWNLOAD_CABLE)' +endif + + +#------------------------------------------------------------------------------ +# BUILD PRE/POST PROCESS +#------------------------------------------------------------------------------ +build_pre_process : + $(BUILD_PRE_PROCESS) + +build_post_process : + $(BUILD_POST_PROCESS) + +.PHONY: build_pre_process build_post_process + + +#------------------------------------------------------------------------------ +# TOOLS +#------------------------------------------------------------------------------ + +# +# Set tool default variables if not already defined. +# If these are defined, they would typically be defined in an +# included makefile fragment. +# +ifeq ($(DEFAULT_CROSS_COMPILE),) +DEFAULT_CROSS_COMPILE := nios2-elf- +endif + +ifeq ($(DEFAULT_STACKREPORT),) +DEFAULT_STACKREPORT := nios2-stackreport +endif + +ifeq ($(DEFAULT_DOWNLOAD),) +DEFAULT_DOWNLOAD := nios2-download +endif + +ifeq ($(DEFAULT_FLASHPROG),) +DEFAULT_FLASHPROG := nios2-flash-programmer +endif + +ifeq ($(DEFAULT_ELFPATCH),) +DEFAULT_ELFPATCH := nios2-elf-insert +endif + +ifeq ($(DEFAULT_RM),) +DEFAULT_RM := rm -f +endif + +ifeq ($(DEFAULT_CP),) +DEFAULT_CP := cp -f +endif + +ifeq ($(DEFAULT_MKDIR),) +DEFAULT_MKDIR := mkdir -p +endif + +# +# Set tool variables to defaults if not already defined. +# If these are defined, they would typically be defined by a +# setting in the generated portion of this makefile. +# +ifeq ($(CROSS_COMPILE),) +CROSS_COMPILE := $(DEFAULT_CROSS_COMPILE) +endif + +ifeq ($(origin CC),default) +CC := $(CROSS_COMPILE)gcc -xc +endif + +ifeq ($(origin CXX),default) +CXX := $(CROSS_COMPILE)gcc -xc++ +endif + +ifeq ($(origin AS),default) +AS := $(CROSS_COMPILE)gcc +endif + +ifeq ($(origin AR),default) +AR := $(CROSS_COMPILE)ar +endif + +ifeq ($(origin LD),default) +LD := $(CROSS_COMPILE)g++ +endif + +ifeq ($(origin RM),default) +RM := $(DEFAULT_RM) +endif + +ifeq ($(NM),) +NM := $(CROSS_COMPILE)nm +endif + +ifeq ($(CP),) +CP := $(DEFAULT_CP) +endif + +ifeq ($(OBJDUMP),) +OBJDUMP := $(CROSS_COMPILE)objdump +endif + +ifeq ($(OBJCOPY),) +OBJCOPY := $(CROSS_COMPILE)objcopy +endif + +ifeq ($(STACKREPORT),) +STACKREPORT := $(DEFAULT_STACKREPORT) --prefix $(CROSS_COMPILE) +else +DISABLE_STACKREPORT := 1 +endif + +ifeq ($(DOWNLOAD),) +DOWNLOAD := $(DEFAULT_DOWNLOAD) +endif + +ifeq ($(FLASHPROG),) +FLASHPROG := $(DEFAULT_FLASHPROG) +endif + +ifeq ($(ELFPATCH),) +ELFPATCH := $(DEFAULT_ELFPATCH) +endif + +ifeq ($(MKDIR),) +MKDIR := $(DEFAULT_MKDIR) +endif + +#------------------------------------------------------------------------------ +# PATTERN RULES TO BUILD OBJECTS +#------------------------------------------------------------------------------ + +define compile.c +@$(ECHO) Info: Compiling $< to $@ +@$(MKDIR) $(@D) +$(CC) -MP -MMD -c $(APP_CPPFLAGS) $(APP_CFLAGS) -o $@ $< +$(CC_POST_PROCESS) +endef + +define compile.cpp +@$(ECHO) Info: Compiling $< to $@ +@$(MKDIR) $(@D) +$(CXX) -MP -MMD -c $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< +$(CXX_POST_PROCESS) +endef + +# If assembling with the compiler, ensure "-Wa," is prepended to all APP_ASFLAGS +ifeq ($(AS),$(patsubst %as,%,$(AS))) +COMMA := , +APP_ASFLAGS := $(filter-out $(APP_CFLAGS),$(addprefix -Wa$(COMMA),$(patsubst -Wa$(COMMA)%,%,$(APP_ASFLAGS)))) +endif + +define compile.s +@$(ECHO) Info: Assembling $< to $@ +@$(MKDIR) $(@D) +$(AS) -MP -MMD -c $(APP_CPPFLAGS) $(APP_CFLAGS) $(APP_ASFLAGS) -o $@ $< +$(AS_POST_PROCESS) +endef + +ifeq ($(MAKE_VERSION),3.81) +.SECONDEXPANSION: + +$(APP_OBJS_C): $(CONFIG_OBJ_DIR)/%.o: $$(call adjust-path-mixed,%.c) + $(compile.c) + +$(APP_OBJS_CPP): $(CONFIG_OBJ_DIR)/%.o: $$(call adjust-path-mixed,%.cpp) + $(compile.cpp) + +$(APP_OBJS_CC): $(CONFIG_OBJ_DIR)/%.o: $$(call adjust-path-mixed,%.cc) + $(compile.cpp) + +$(APP_OBJS_CXX): $(CONFIG_OBJ_DIR)/%.o: $$(call adjust-path-mixed,%.cxx) + $(compile.cpp) + +$(APP_OBJS_S): $(CONFIG_OBJ_DIR)/%.o: $$(call adjust-path-mixed,%.S) + $(compile.s) + +$(APP_OBJS_SS): $(CONFIG_OBJ_DIR)/%.o: $$(call adjust-path-mixed,%.s) + $(compile.s) + +endif # MAKE_VERSION != 3.81 + +$(CONFIG_OBJ_DIR)/%.o: %.c + $(compile.c) + +$(CONFIG_OBJ_DIR)/%.o: %.cpp + $(compile.cpp) + +$(CONFIG_OBJ_DIR)/%.o: %.cc + $(compile.cpp) + +$(CONFIG_OBJ_DIR)/%.o: %.cxx + $(compile.cpp) + +$(CONFIG_OBJ_DIR)/%.o: %.S + $(compile.s) + +$(CONFIG_OBJ_DIR)/%.o: %.s + $(compile.s) + + +#------------------------------------------------------------------------------ +# PATTERN RULES TO INTERMEDIATE FILES +#------------------------------------------------------------------------------ + +$(CONFIG_OBJ_DIR)/%.s: %.c + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CC) -S $(APP_CPPFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.s: %.cpp + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CXX) -S $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.s: %.cc + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CXX) -S $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.s: %.cxx + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CXX) -S $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.i: %.c + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CC) -E $(APP_CPPFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.i: %.cpp + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CXX) -E $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.i: %.cc + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CXX) -E $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< + +$(CONFIG_OBJ_DIR)/%.i: %.cxx + @$(ECHO) Info: Compiling $< to $@ + @$(MKDIR) $(@D) + $(CXX) -E $(APP_CPPFLAGS) $(APP_CXXFLAGS) $(APP_CFLAGS) -o $@ $< + + +#------------------------------------------------------------------------------ +# TARGET RULES +#------------------------------------------------------------------------------ + +.PHONY : help +help : + @$(ECHO) "Summary of Makefile targets" + @$(ECHO) " Build targets:" + @$(ECHO) " all (default) - Application and all libraries (including BSP)" + @$(ECHO) " bsp - Just the BSP" + @$(ECHO) " libs - All libraries (including BSP)" + @$(ECHO) " flash - All flash files" + @$(ECHO) " mem_init_generate - All memory initialization files" +ifeq ($(QSYS),1) + @$(ECHO) " mem_init_install - This target is deprecated for QSys Systems" + @$(ECHO) " --> Use the mem_init_generate target and then" + @$(ECHO) " add the generated meminit.qip file to your" + @$(ECHO) " Quartus II Project." +else # if QSYS != 1 + @$(ECHO) " mem_init_install - Copy memory initialization files to Quartus II project" +endif # QSYS == 1 + @$(ECHO) + @$(ECHO) " Clean targets:" + @$(ECHO) " clean_all - Application and all libraries (including BSP)" + @$(ECHO) " clean - Just the application" + @$(ECHO) " clean_bsp - Just the BSP" + @$(ECHO) " clean_libs - All libraries (including BSP)" + @$(ECHO) + @$(ECHO) " Run targets:" + @$(ECHO) " download-elf - Download and run your elf executable" + @$(ECHO) " program-flash - Program flash contents to the board" + +# Handy rule to skip making libraries and just make application. +.PHONY : app +app : $(ELF) + +ifeq ($(CREATE_OBJDUMP), 1) +app : $(OBJDUMP_NAME) +endif + +ifeq ($(CREATE_ELF_DERIVED_FILES),1) +app : elf_derived_files +endif + +.PHONY: elf_derived_files +elf_derived_files: default_mem_init + +# Handy rule for making just the BSP. +.PHONY : bsp +bsp : + @$(ECHO) Info: Building $(BSP_ROOT_DIR) + @$(MAKE) --no-print-directory -C $(BSP_ROOT_DIR) + + +# Make sure all makeable libraries (including the BSP) are up-to-date. +LIB_TARGETS := $(patsubst %,%-recurs-make-lib,$(MAKEABLE_LIBRARY_ROOT_DIRS)) + +.PHONY : libs +libs : $(LIB_TARGETS) + +ifneq ($(strip $(LIB_TARGETS)),) +$(LIB_TARGETS): %-recurs-make-lib: + @$(ECHO) Info: Building $* + $(MAKE) --no-print-directory -C $* +endif + +ifneq ($(strip $(APP_LDDEPS)),) +$(APP_LDDEPS): libs + @true +endif + +# Rules to force your project to rebuild or relink +# .force_relink file will cause any application that depends on this project to relink +# .force_rebuild file will cause this project to rebuild object files +# .force_rebuild_all file will cause this project and any project that depends on this project to rebuild object files + +FORCE_RELINK_DEP := .force_relink +FORCE_REBUILD_DEP := .force_rebuild +FORCE_REBUILD_ALL_DEP := .force_rebuild_all +FORCE_REBUILD_DEP_LIST := $(CONFIG_OBJ_DIR)/$(FORCE_RELINK_DEP) $(CONFIG_OBJ_DIR)/$(FORCE_REBUILD_DEP) $(FORCE_REBUILD_ALL_DEP) + +$(FORCE_REBUILD_DEP_LIST): + +$(APP_OBJS): $(wildcard $(CONFIG_OBJ_DIR)/$(FORCE_REBUILD_DEP)) $(wildcard $(addsuffix /$(FORCE_REBUILD_ALL_DEP), . $(ALT_LIBRARY_DIRS))) + +$(ELF): $(wildcard $(addsuffix /$(FORCE_RELINK_DEP), $(CONFIG_OBJ_DIR) $(ALT_LIBRARY_DIRS))) + + +# Clean just the application. +.PHONY : clean +ifeq ($(CREATE_ELF_DERIVED_FILES),1) +clean : clean_elf_derived_files +endif + +clean : + @$(RM) -r $(ELF) $(OBJDUMP_NAME) $(LINKER_MAP_NAME) $(OBJ_ROOT_DIR) $(RUNTIME_ROOT_DIR) $(FORCE_REBUILD_DEP_LIST) + @$(ECHO) [$(APP_NAME) clean complete] + +# Clean just the BSP. +.PHONY : clean_bsp +clean_bsp : + @$(ECHO) Info: Cleaning $(BSP_ROOT_DIR) + @$(MAKE) --no-print-directory -C $(BSP_ROOT_DIR) clean + +# Clean all makeable libraries including the BSP. +LIB_CLEAN_TARGETS := $(patsubst %,%-recurs-make-clean-lib,$(MAKEABLE_LIBRARY_ROOT_DIRS)) + +.PHONY : clean_libs +clean_libs : $(LIB_CLEAN_TARGETS) + +ifneq ($(strip $(LIB_CLEAN_TARGETS)),) +$(LIB_CLEAN_TARGETS): %-recurs-make-clean-lib: + @$(ECHO) Info: Cleaning $* + $(MAKE) --no-print-directory -C $* clean +endif + +.PHONY: clean_elf_derived_files +clean_elf_derived_files: mem_init_clean + +# Clean application and all makeable libraries including the BSP. +.PHONY : clean_all +clean_all : clean mem_init_clean clean_libs + +# Include the dependency files unless the make goal is performing a clean +# of the application. +ifneq ($(firstword $(MAKECMDGOALS)),clean) +ifneq ($(firstword $(MAKECMDGOALS)),clean_all) +-include $(APP_DEPS) +endif +endif + +.PHONY : download-elf +download-elf : $(ELF) + @if [ "$(DOWNLOAD)" = "none" ]; \ + then \ + $(ECHO) Downloading $(ELF) not supported; \ + else \ + $(ECHO) Info: Downloading $(ELF); \ + $(DOWNLOAD) --go --cpu_name=$(CPU_NAME) $(DOWNLOAD_CABLE_FLAG) $(SOPC_SYSID_FLAG) $(DOWNLOAD_JDI_FLAG) $(WRITE_GMON_OPTION) $(ELF); \ + fi + +# Delete the target of a rule if it has changed and its commands exit +# with a nonzero exit status. +.DELETE_ON_ERROR: + +# Rules for flash programming commands +PROGRAM_FLASH_SUFFIX := -program +PROGRAM_FLASH_TARGET := $(addsuffix $(PROGRAM_FLASH_SUFFIX), $(FLASH_FILES)) + +.PHONY : program-flash +program-flash : $(PROGRAM_FLASH_TARGET) + +.PHONY : $(PROGRAM_FLASH_TARGET) +$(PROGRAM_FLASH_TARGET) : flash + @if [ "$(FLASHPROG)" = "none" ]; \ + then \ + $(ECHO) Programming flash not supported; \ + else \ + $(ECHO) Info: Programming $(basename $@).flash; \ + if [ -z "$($(basename $@)_EPCS_FLAGS)" ]; \ + then \ + $(ECHO) $(FLASHPROG) $(SOPC_SYSID_FLAG) --base=$($(basename $@)_START) $(basename $@).flash; \ + $(FLASHPROG) $(DOWNLOAD_CABLE_FLAG) $(SOPC_SYSID_FLAG) --base=$($(basename $@)_START) $(basename $@).flash; \ + else \ + $(ECHO) $(FLASHPROG) $(SOPC_SYSID_FLAG) --epcs --base=$($(basename $@)_START) $(basename $@).flash; \ + $(FLASHPROG) $(DOWNLOAD_CABLE_FLAG) $(SOPC_SYSID_FLAG) --epcs --base=$($(basename $@)_START) $(basename $@).flash; \ + fi \ + fi + + +# Rules for simulating with an HDL Simulator [QSYS only] +ifeq ($(QSYS),1) +IP_MAKE_SIMSCRIPT := ip-make-simscript + +ifeq ($(VSIM),) +VSIM_EXE := "$(if $(VSIM_DIR),$(VSIM_DIR)/,)vsim" +ifeq ($(ENABLE_VSIM_GUI),1) +VSIM := $(VSIM_EXE) -gui +else +VSIM := $(VSIM_EXE) -c +endif # ENABLE_VSIM_GUI == 1 +endif # VSIM not set + +ifeq ($(SPD),) +ifneq ($(ABS_QUARTUS_PROJECT_DIR),) +ifneq ($(SOPC_NAME),) +SPD_LOCATION = $(ABS_QUARTUS_PROJECT_DIR)/$(SOPC_NAME)_tb/$(SOPC_NAME)_tb/$(SOPC_NAME)_tb.spd +LEGACY_SPD_LOCATION = $(ABS_QUARTUS_PROJECT_DIR)/$(SOPC_NAME)_tb.spd +SPD = $(if $(wildcard $(SPD_LOCATION)),$(SPD_LOCATION),$(LEGACY_SPD_LOCATION)) +endif # SOPC_NAME set +endif # ABS_QUARTUS_PROJECT_DIR set +endif # SPD == empty string + +ifeq ($(MSIM_SCRIPT),) +SIM_SCRIPT_DIR := $(RUNTIME_ROOT_DIR)/sim +MSIM_SCRIPT := $(SIM_SCRIPT_DIR)/mentor/msim_setup.tcl +endif # MSIM_SCRIPT == empty string + +ifeq ($(MAKE_VERSION),3.81) +ABS_MEM_INIT_DESCRIPTOR_FILE := $(abspath $(MEM_INIT_DESCRIPTOR_FILE)) +else +ABS_MEM_INIT_DESCRIPTOR_FILE := $(call adjust-path-mixed,$(shell pwd))/$(MEM_INIT_DESCRIPTOR_FILE) +endif + +$(MSIM_SCRIPT): $(SPD) $(MEM_INIT_DESCRIPTOR_FILE) +ifeq ($(SPD),) + $(error No SPD file specified. Ensure QUARTUS_PROJECT_DIR variable is set) +endif + @$(MKDIR) $(SIM_SCRIPT_DIR) + $(IP_MAKE_SIMSCRIPT) --spd=$(SPD) --spd=$(MEM_INIT_DESCRIPTOR_FILE) --output-directory=$(SIM_SCRIPT_DIR) + +VSIM_COMMAND = \ + cd $(dir $(MSIM_SCRIPT)) && \ + $(VSIM) -do "do $(notdir $(MSIM_SCRIPT)); ld; $(if $(VSIM_RUN_TIME),run ${VSIM_RUN_TIME};quit;)" + +.PHONY: sim +sim: $(MSIM_SCRIPT) mem_init_generate +ifeq ($(MSIM_SCRIPT),) + $(error MSIM_SCRIPT not set) +endif + $(VSIM_COMMAND) + +endif # QSYS == 1 + + +#------------------------------------------------------------------------------ +# ELF TARGET RULE +#------------------------------------------------------------------------------ +# Rule for constructing the executable elf file. +$(ELF) : $(APP_OBJS) $(LINKER_SCRIPT) $(APP_LDDEPS) + @$(ECHO) Info: Linking $@ + $(LD) $(APP_LDFLAGS) $(APP_CFLAGS) -o $@ $(filter-out $(CRT0),$(APP_OBJS)) $(APP_LIBS) $(APP_BSP_DEP_LIBS) +ifneq ($(DISABLE_ELFPATCH),1) + $(ELFPATCH) $@ $(ELF_PATCH_FLAG) +endif +ifneq ($(DISABLE_STACKREPORT),1) + @bash -c "$(STACKREPORT) $@" +endif + +$(OBJDUMP_NAME) : $(ELF) + @$(ECHO) Info: Creating $@ + $(OBJDUMP) $(OBJDUMP_FLAGS) $< >$@ + +# Rule for printing the name of the elf file +.PHONY: print-elf-name +print-elf-name: + @$(ECHO) $(ELF) + + diff --git a/software/sys_controller/av_controller.c b/software/sys_controller/av_controller.c new file mode 100644 index 0000000..1b5e8d4 --- /dev/null +++ b/software/sys_controller/av_controller.c @@ -0,0 +1,1393 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include "system.h" +#include "string.h" +#include "altera_avalon_pio_regs.h" +#include "Altera_UP_SD_Card_Avalon_Interface_mod.h" +#include "altera_epcq_controller_mod.h" +#include "i2c_opencores.h" +#include "tvp7002.h" +#include "ths7353.h" +#include "video_modes.h" +#include "lcd.h" +#include "sysconfig.h" +#include "it6613.h" +#include "HDMI_TX.h" +#include "hdmitx.h" +#include "ci_crc.h" + +alt_u8 fw_ver_major = 0; +alt_u8 fw_ver_minor = 64; +#define FW_UPDATE_RETRIES 3 + +#define LINECNT_THOLD 1 +#define STABLE_THOLD 1 +#define MIN_VALID_LINES 100 +#define SYNC_LOSS_THOLD 5 + +#define MAINLOOP_SLEEP_US 10000 + +// AV control word: +// [20:17] [16:13] [12:10] [9:8] [7] [6] [5:4] [3] [2] [1] [0] +// | H_MASK[3:0] | V_MASK[3:0] | SCANLINESTR[2:0] | RESERVED[1:0] | TVP_CLKSEL | SLEN | L3MODE[1:0] | L3EN || BTN3 | BTN2 | BTN1 | + +#define SCANLINESTR_MAX 0x07 +#define HV_MASK_MAX 0x0f +#define L3_MODE_MAX 3 +#define S480P_MODE_MAX 2 +#define SL_MODE_MAX 2 +#define SYNC_LPF_MAX 3 +#define VIDEO_LPF_MAX 5 +#define SAMPLER_PHASE_MIN -16 +#define SAMPLER_PHASE_MAX 15 + +//#define TVP_CLKSEL_BIT (1<<7) + +#define RC_MASK 0x0000ffff +#define PB_MASK 0x00030000 +#define PB0_MASK 0x00010000 +#define PB1_MASK 0x00020000 +#define HDMITX_MODE_MASK 0x00040000 + +static const char *rc_keydesc[] = { "1", "2", "3", "MENU", "BACK", "UP", "DOWN", "LEFT", "RIGHT", "INFO", "LCD_BACKLIGHT", "HOTKEY1", "HOTKEY2", "HOTKEY3"}; +#define REMOTE_MAX_KEYS (sizeof(rc_keydesc)/sizeof(char*)) +alt_u16 rc_keymap[REMOTE_MAX_KEYS] = {0x2088, 0x2048, 0x20c8, 0x2008, 0x20d8, 0x2000, 0x2080, 0x20c0, 0x2040, 0x2058, 0x2010, 0x20e8, 0x2018, 0x2098}; + +typedef enum { + RC_BTN1 = 0, + RC_BTN2, + RC_BTN3, + RC_MENU, + RC_BACK, + RC_UP, + RC_DOWN, + RC_LEFT, + RC_RIGHT, + RC_INFO, + RC_LCDBL, + RC_HOTKEY1, + RC_HOTKEY2, + RC_HOTKEY3, +} rc_code_t; + +#define lcd_write_menu() lcd_write((char*)&menu_row1, (char*)&menu_row2) +#define lcd_write_status() lcd_write((char*)&row1, (char*)&row2) + +static const char *avinput_str[] = { "NO MODE", "AV1: RGBS", "AV1: RGsB", "AV2: YPbPr", "AV2: RGsB", "AV3: RGBHV", "AV3: RGBS", "AV3: RGsB" }; +static const char *l3_mode_desc[] = { "Generic 16:9", "Generic 4:3", "320x240 optim.", "256x240 optim." }; +static const char *s480p_desc[] = { "Auto", "DTV 480p", "VGA 640x480" }; +static const char *sl_mode_desc[] = { "Off", "Horizontal", "Vertical" }; +static const char *sync_lpf_desc[] = { "Off", "33MHz", "10MHz", "2.5MHz" }; +static const char *video_lpf_desc[] = { "Auto", "Off", "95MHz (HDTV II)", "35MHz (HDTV I)", "16MHz (EDTV)", "9MHz (SDTV)" }; + +typedef enum { + AV_KEEP = 0, + AV1_RGBs = 1, + AV1_RGsB = 2, + AV2_YPBPR = 3, + AV2_RGsB = 4, + AV3_RGBHV = 5, + AV3_RGBs = 6, + AV3_RGsB = 7 +} avinput_t; + +// In reverse order of importance +typedef enum { + NO_CHANGE = 0, + INFO_CHANGE = 1, + MODE_CHANGE = 2, + TX_MODE_CHANGE = 3, + ACTIVITY_CHANGE = 4 +} status_t; + +typedef enum { + SCANLINE_MODE, + SCANLINE_STRENGTH, + SCANLINE_ID, + H_MASK, + V_MASK, + SAMPLER_480P, + SAMPLER_PHASE, + YPBPR_COLORSPACE, + SYNC_LPF, + VIDEO_LPF, + LINETRIPLE_ENABLE, + LINETRIPLE_MODE, + TX_MODE, + FW_UPDATE, + SAVE_CONFIG +} menuitem_id; + +typedef enum { + NO_ACTION = 0, + NEXT_PAGE = 1, + PREV_PAGE = 2, + VAL_PLUS = 3, + VAL_MINUS = 4, +} menucode_id; + +typedef enum { + TX_HDMI = 0, + TX_DVI = 1 +} tx_mode_t; + +typedef struct { + alt_u8 sl_mode; + alt_u8 sl_str; + alt_u8 sl_id; + alt_u8 linemult_target; + alt_u8 l3_mode; + alt_u8 h_mask; + alt_u8 v_mask; + alt_u8 tx_mode; + alt_u8 s480p_mode; + alt_8 sampler_phase; + alt_u8 ypbpr_cs; + alt_u8 sync_lpf; + alt_u8 video_lpf; +} avconfig_t; + +// Target configuration +avconfig_t tc; + +//TODO: transform binary values into flags +typedef struct { + alt_u32 totlines; + alt_u32 clkcnt; + alt_u8 progressive; + alt_u8 macrovis; + alt_u8 refclk; + alt_8 id; + alt_u8 sync_active; + alt_u8 linemult; + avinput_t avinput; + // Current configuration + avconfig_t cc; +} avmode_t; + +// Current mode +avmode_t cm; + +typedef struct { + const menuitem_id id; + const char *desc; +} menuitem_t; + +const menuitem_t menu[] = { + { SCANLINE_MODE, "Scanlines" }, + { SCANLINE_STRENGTH, "Scanline str." }, + { SCANLINE_ID, "Scanline id" }, + { H_MASK, "Horizontal mask" }, + { V_MASK, "Vertical mask" }, + { SAMPLER_480P, "480p in sampler" }, + { SAMPLER_PHASE, "Sampling phase" }, + { YPBPR_COLORSPACE, "YPbPr in ColSpa" }, + { SYNC_LPF, "Analog sync LPF" }, + { VIDEO_LPF, "Video LPF" }, + { LINETRIPLE_ENABLE, "240p linetriple" }, + { LINETRIPLE_MODE, "Linetriple mode" }, + { TX_MODE, "TX mode" }, +//#ifndef DEBUG + { FW_UPDATE, "Firmware update" }, +//#endif + { SAVE_CONFIG, "Save settings" }, +}; + +#define MENUITEMS (sizeof(menu)/sizeof(menuitem_t)) + +typedef struct { + char fw_key[4]; + alt_u8 version_major; + alt_u8 version_minor; + char version_suffix[8]; + alt_u32 hdr_len; + alt_u32 data_len; + alt_u32 data_crc; + alt_u32 hdr_crc; +} fw_hdr; + +#define USERDATA_HDR_SIZE 11 +typedef struct { + char userdata_key[8]; + alt_u8 version_major; + alt_u8 version_minor; + alt_u8 num_entries; +} userdata_hdr; + +#define USERDATA_ENTRY_HDR_SIZE 2 +typedef struct { + alt_u8 type; + alt_u8 entry_len; +} userdata_entry; + +typedef enum { + UDE_REMOTE_MAP = 0, + UDE_AVCONFIG, +} userdata_entry_type; + +extern mode_data_t video_modes[]; +extern ypbpr_to_rgb_csc_t csc_coeffs[]; +extern alt_epcq_controller_dev epcq_controller_0; + +alt_epcq_controller_dev *epcq_controller_dev; +alt_up_sd_card_dev *sdcard_dev; + +alt_u8 target_typemask; +alt_u8 target_type; +alt_u8 stable_frames; + +char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1]; + +// EPCS16 pagesize is 256 bytes +// Flash is split 50-50 to FW and userdata, 1MB each +#define PAGESIZE 256 +#define PAGES_PER_SECTOR 256 +#define USERDATA_OFFSET 0x100000 +#define USERDATA_MAX_SIZE 0x1000 //4KB should be enough + +// SD controller uses 512-byte chunks +#define SD_BUFFER_SIZE 512 + +short int sd_fw_handle; + +alt_u8 menu_active, menu_page; +alt_u32 remote_code, remote_code_prev; +alt_u32 btn_code, btn_code_prev; + +/*alt_u8 reverse_bits(alt_u8 b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +}*/ + +int check_flash() { + epcq_controller_dev = &epcq_controller_0; + + if ((epcq_controller_dev == NULL) || !(epcq_controller_dev->is_epcs && (epcq_controller_dev->page_size == PAGESIZE))) + return -1; + + //printf("Flash size in bytes: %d\nSector size: %d (%d pages)\nPage size: %d\n", epcq_controller_dev->size_in_bytes, epcq_controller_dev->sector_size, epcq_controller_dev->sector_size/epcq_controller_dev->page_size, epcq_controller_dev->page_size); + + return 0; +} + +int read_flash(alt_u32 offset, alt_u32 length, alt_u8 *dstbuf) { + int retval, i; + + retval = alt_epcq_controller_read(&epcq_controller_dev->dev, offset, dstbuf, length); + if (retval != 0) + return -1; + + for (i=0; i> 24; + + return 0; +} + +int write_flash_page(alt_u8 *pagedata, alt_u32 length, alt_u32 pagenum) { + int retval, i; + + if ((pagenum % PAGES_PER_SECTOR) == 0) { + printf("Erasing sector %u\n", (unsigned)(pagenum/PAGES_PER_SECTOR)); + retval = alt_epcq_controller_erase_block(&epcq_controller_dev->dev, pagenum*PAGESIZE); + + if (retval != 0) { + strncpy(menu_row1, "Flash erase", LCD_ROW_LEN+1); + sniprintf(menu_row1, LCD_ROW_LEN+1, "error %d", retval); + menu_row2[0] = '\0'; + printf("Flash erase error, sector %u\nRetval %d\n", (unsigned)(pagenum/PAGES_PER_SECTOR), retval); + return -200; + } + } + + // Bit-reverse bytes for flash + for (i=0; i> 24; + + retval = alt_epcq_controller_write_block(&epcq_controller_dev->dev, (pagenum/PAGES_PER_SECTOR)*PAGES_PER_SECTOR*PAGESIZE, pagenum*PAGESIZE, pagedata, length); + + if (retval != 0) { + strncpy(menu_row1, "Flash write", LCD_ROW_LEN+1); + strncpy(menu_row2, "error", LCD_ROW_LEN+1); + printf("Flash write error, page %u\nRetval %d\n", (unsigned)pagenum, retval); + return -201; + } + + return retval; +} + +int verify_flash(alt_u32 offset, alt_u32 length, alt_u32 golden_crc, alt_u8 *tmpbuf) { + alt_u32 crcval=0, i, bytes_to_read; + int retval; + + for (i=0; i 512)) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid read cmd"); + menu_row2[0] = '\0'; + return -1; + } + + if (!Read_Sector_Data((offset/SD_BUFFER_SIZE), 0)) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "SD read failure"); + menu_row2[0] = '\0'; + return -2; + } + + // Copy buffer to SW + for (i=0; ibase, i); + *((alt_u32*)(dstbuf+i)) = tmp; + } + + return 0; +} + +int check_sdcard(alt_u8 *databuf) { + sdcard_dev = alt_up_sd_card_open_dev(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_NAME); + + if ((sdcard_dev == NULL) || !alt_up_sd_card_is_Present()) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "No SD card det."); + menu_row2[0] = '\0'; + return 1; + } + + return read_sd_block(0, 512, databuf); +} + +int check_fw_header(alt_u8 *databuf, fw_hdr *hdr) { + alt_u32 crcval, tmp; + + strncpy(hdr->fw_key, (char*)databuf, 4); + if (strncmp(hdr->fw_key, "OSSC", 4)) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid image"); + menu_row2[0] = '\0'; + return 1; + } + + hdr->version_major = databuf[4]; + hdr->version_minor = databuf[5]; + strncpy(hdr->version_suffix, (char*)(databuf+6), 8); + hdr->version_suffix[7] = 0; + + memcpy(&tmp, databuf+14, 4); + hdr->hdr_len = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp); + memcpy(&tmp, databuf+18, 4); + hdr->data_len = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp); + memcpy(&tmp, databuf+22, 4); + hdr->data_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp); + // Always at bytes [508-511] + memcpy(&tmp, databuf+508, 4); + hdr->hdr_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp); + + if (hdr->hdr_len < 26 || hdr->hdr_len > 508) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid header"); + menu_row2[0] = '\0'; + return -1; + } + + crcval = crcCI(databuf, hdr->hdr_len, 1); + + if (crcval != hdr->hdr_crc) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid hdr CRC"); + menu_row2[0] = '\0'; + return -2; + } + + return 0; +} + +int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf) { + alt_u32 crcval=0, i, bytes_to_read; + int retval; + + for (i=0; i PAGESIZE) { + retval = write_flash_page(databuf+PAGESIZE, (bytes_to_rw-PAGESIZE), (i/PAGESIZE)+1); + if (retval != 0) + goto failure; + } + } + + strncpy(menu_row1, "Verifying flash", LCD_ROW_LEN+1); + strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1); + lcd_write_menu(); + retval = verify_flash(0, fw_header.data_len, fw_header.data_crc, databuf); + if (retval != 0) + goto failure; + + return 0; + + +failure: + lcd_write_menu(); + usleep(1000000); + + // Probable rw error, retry update + if ((retval <= -200) && (retries > 0)) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Retrying update"); + retries--; + goto update_init; + } + + return -1; +} + +int write_userdata() { + alt_u8 databuf[PAGESIZE]; + int retval; + + strncpy((char*)databuf, "USRDATA", 8); + databuf[8] = fw_ver_major; + databuf[9] = fw_ver_minor; + databuf[10] = 2; + + retval = write_flash_page(databuf, USERDATA_HDR_SIZE, (USERDATA_OFFSET/PAGESIZE)); + if (retval != 0) { + return -1; + } + + databuf[0] = UDE_REMOTE_MAP; + databuf[1] = 4+sizeof(rc_keymap); + databuf[2] = databuf[3] = 0; //padding + memcpy(databuf+4, rc_keymap, sizeof(rc_keymap)); + + retval = write_flash_page(databuf, databuf[1], (USERDATA_OFFSET/PAGESIZE)+1); + if (retval != 0) { + return -1; + } + + databuf[0] = UDE_AVCONFIG; + databuf[1] = 4+sizeof(avconfig_t); + databuf[2] = databuf[3] = 0; //padding + memcpy(databuf+4, &tc, sizeof(avconfig_t)); + + retval = write_flash_page(databuf, databuf[1], (USERDATA_OFFSET/PAGESIZE)+2); + if (retval != 0) { + return -1; + } + + return 0; +} + +int read_userdata() { + int retval, i; + alt_u8 databuf[PAGESIZE]; + userdata_hdr udhdr; + userdata_entry udentry; + + retval = read_flash(USERDATA_OFFSET, USERDATA_HDR_SIZE, databuf); + if (retval != 0) { + printf("Flash read error\n"); + return -1; + } + + strncpy(udhdr.userdata_key, (char*)databuf, 8); + if (strncmp(udhdr.userdata_key, "USRDATA", 8)) { + printf("No userdata found on flash\n"); + return 1; + } + + udhdr.version_major = databuf[8]; + udhdr.version_minor = databuf[9]; + udhdr.num_entries = databuf[10]; + + //TODO: check version compatibility + printf("Userdata: v%u.%.2u, %u entries\n", udhdr.version_major, udhdr.version_minor, udhdr.num_entries); + + for (i=0; i 0)) + tc.sl_mode--; + else if ((code == VAL_PLUS) && (tc.sl_mode < SL_MODE_MAX)) + tc.sl_mode++; + strncpy(menu_row2, sl_mode_desc[tc.sl_mode], LCD_ROW_LEN+1); + break; + case SCANLINE_STRENGTH: + if ((code == VAL_MINUS) && (tc.sl_str > 0)) + tc.sl_str--; + else if ((code == VAL_PLUS) && (tc.sl_str < SCANLINESTR_MAX)) + tc.sl_str++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%u%%", ((tc.sl_str+1)*125)/10); + break; + case SCANLINE_ID: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) + tc.sl_id = !tc.sl_id; + sniprintf(menu_row2, LCD_ROW_LEN+1, tc.sl_id ? "Odd" : "Even"); + break; + case H_MASK: + if ((code == VAL_MINUS) && (tc.h_mask > 0)) + tc.h_mask--; + else if ((code == VAL_PLUS) && (tc.h_mask < HV_MASK_MAX)) + tc.h_mask++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", tc.h_mask<<2); + break; + case V_MASK: + if ((code == VAL_MINUS) && (tc.v_mask > 0)) + tc.v_mask--; + else if ((code == VAL_PLUS) && (tc.v_mask < HV_MASK_MAX)) + tc.v_mask++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", tc.v_mask<<2); + break; + case SAMPLER_480P: + if ((code == VAL_MINUS) && (tc.s480p_mode > 0)) + tc.s480p_mode--; + else if ((code == VAL_PLUS) && (tc.s480p_mode < S480P_MODE_MAX)) + tc.s480p_mode++; + strncpy(menu_row2, s480p_desc[tc.s480p_mode], LCD_ROW_LEN+1); + break; + case SAMPLER_PHASE: + if ((code == VAL_MINUS) && (tc.sampler_phase > SAMPLER_PHASE_MIN)) + tc.sampler_phase--; + else if ((code == VAL_PLUS) && (tc.sampler_phase < SAMPLER_PHASE_MAX)) + tc.sampler_phase++; + sniprintf(menu_row2, LCD_ROW_LEN+1, "%d deg", ((tc.sampler_phase-SAMPLER_PHASE_MIN)*1125)/100); + break; + case YPBPR_COLORSPACE: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) + tc.ypbpr_cs = !tc.ypbpr_cs; + strncpy(menu_row2, csc_coeffs[tc.ypbpr_cs].name, LCD_ROW_LEN+1); + break; + case SYNC_LPF: + if ((code == VAL_MINUS) && (tc.sync_lpf > 0)) + tc.sync_lpf--; + else if ((code == VAL_PLUS) && (tc.sync_lpf < SYNC_LPF_MAX)) + tc.sync_lpf++; + strncpy(menu_row2, sync_lpf_desc[tc.sync_lpf], LCD_ROW_LEN+1); + break; + case VIDEO_LPF: + if ((code == VAL_MINUS) && (tc.video_lpf > 0)) + tc.video_lpf--; + else if ((code == VAL_PLUS) && (tc.video_lpf < VIDEO_LPF_MAX)) + tc.video_lpf++; + strncpy(menu_row2, video_lpf_desc[tc.video_lpf], LCD_ROW_LEN+1); + break; + case LINETRIPLE_ENABLE: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) + tc.linemult_target = !tc.linemult_target; + sniprintf(menu_row2, LCD_ROW_LEN+1, tc.linemult_target ? "On" : "Off"); + break; + case LINETRIPLE_MODE: + if ((code == VAL_MINUS) && (tc.l3_mode > 0)) + tc.l3_mode--; + else if ((code == VAL_PLUS) && (tc.l3_mode < L3_MODE_MAX)) + tc.l3_mode++; + strncpy(menu_row2, l3_mode_desc[tc.l3_mode], LCD_ROW_LEN+1); + break; + case TX_MODE: + if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & HDMITX_MODE_MASK) && ((code == VAL_MINUS) || (code == VAL_PLUS))) { + tc.tx_mode = !tc.tx_mode; + TX_enable(tc.tx_mode); + } + sniprintf(menu_row2, LCD_ROW_LEN+1, tc.tx_mode ? "DVI" : "HDMI"); + break; +//#ifndef DEBUG + case FW_UPDATE: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) { + retval = fw_update(); + if (retval == 0) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "Fw update OK"); + sniprintf(menu_row2, LCD_ROW_LEN+1, "Please restart"); + } else { + sniprintf(menu_row1, LCD_ROW_LEN+1, "FW not"); + sniprintf(menu_row2, LCD_ROW_LEN+1, "updated"); + } + } else { + sniprintf(menu_row2, LCD_ROW_LEN+1, "press <- or ->"); + } + break; +//#endif + case SAVE_CONFIG: + if ((code == VAL_MINUS) || (code == VAL_PLUS)) { + retval = write_userdata(); + if (retval == 0) { + sniprintf(menu_row2, LCD_ROW_LEN+1, "Done"); + } else { + sniprintf(menu_row2, LCD_ROW_LEN+1, "error"); + } + } else { + sniprintf(menu_row2, LCD_ROW_LEN+1, "press <- or ->"); + } + break; + default: + sniprintf(menu_row2, LCD_ROW_LEN+1, "MISSING ITEM"); + break; + } + + lcd_write_menu(); + + return; +} + +void read_control() { + if (remote_code_prev == 0) { + if (remote_code == rc_keymap[RC_MENU]) { + menu_active = !menu_active; + + if (menu_active) { + display_menu(1); + } else { + lcd_write_status(); + } + } else if (remote_code == rc_keymap[RC_BACK]) { + menu_active = 0; + lcd_write_status(); + } else if (remote_code == rc_keymap[RC_INFO]) { + sniprintf(menu_row1, LCD_ROW_LEN+1, "VMod: %s", video_modes[cm.id].name); + //sniprintf(menu_row1, LCD_ROW_LEN+1, "0x%x 0x%x 0x%x", ths_readreg(THS_CH1), ths_readreg(THS_CH2), ths_readreg(THS_CH3)); + sniprintf(menu_row2, LCD_ROW_LEN+1, "LO: %u VSM: %u", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16); + lcd_write_menu(); + printf("Mod: %s\n", video_modes[cm.id].name); + printf("Lines: %u M: %u\n", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, cm.macrovis); + } else if (remote_code == rc_keymap[RC_LCDBL]) { + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) ^ (1<<1))); + } else if (remote_code == rc_keymap[RC_HOTKEY1]) { + tc.sl_mode = (tc.sl_mode > 0) ? 0 : 1; + } else if (remote_code == rc_keymap[RC_HOTKEY2]) { + if (tc.sl_str > 0) + tc.sl_str--; + } else if (remote_code == rc_keymap[RC_HOTKEY3]) { + if (tc.sl_str < SCANLINESTR_MAX) + tc.sl_str++; + } + } + + if (btn_code_prev == 0) { + if (btn_code & PB1_MASK) + tc.sl_mode = (tc.sl_mode > 0) ? 0 : 1; + } + + if (menu_active) { + display_menu(0); + return; + } + + if (remote_code_prev != 0) + return; +} + +void set_lpf(alt_u8 lpf) { + alt_u32 pclk; + pclk = (clkrate[cm.refclk]/cm.clkcnt)*video_modes[cm.id].h_total; + printf("PCLK: %uHz\n", pclk); + + //Auto + if (lpf == 0) { + switch (target_type) { + case VIDEO_PC: + tvp_set_lpf((pclk < 30000000) ? 0x0F : 0); + ths_set_lpf(THS_LPF_BYPASS); + break; + case VIDEO_HDTV: + tvp_set_lpf(0); + ths_set_lpf(THS_LPF_BYPASS); + break; + case VIDEO_EDTV: + tvp_set_lpf(0); + ths_set_lpf(1); + break; + case VIDEO_SDTV: + case VIDEO_LDTV: + tvp_set_lpf(0); + ths_set_lpf(0); + break; + default: + break; + } + } else { + tvp_set_lpf((tc.video_lpf == 2) ? 0x0F : 0); + ths_set_lpf((tc.video_lpf > 2) ? (VIDEO_LPF_MAX-tc.video_lpf) : THS_LPF_BYPASS); + } +} + +// Check if input video status / target configuration has changed +status_t get_status(tvp_input_t input) { + alt_u32 data1, data2; + alt_u32 totlines, clkcnt; + alt_u8 macrovis, progressive; + alt_u8 refclk; + alt_u8 sync_active; + alt_u8 vsyncmode; + alt_u16 fpga_totlines; + status_t status; + static alt_u8 act_ctr; + + status = NO_CHANGE; + + sync_active = tvp_check_sync(input); + vsyncmode = IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16; + + // TVP7002 may randomly report "no sync" (especially with arcade boards), + // thus disable output only after N consecutive "no sync"-events + if (!cm.sync_active && sync_active) { + cm.sync_active = sync_active; + status = ACTIVITY_CHANGE; + act_ctr = 0; + } else if (cm.sync_active && !sync_active) { + printf("Sync down in %u...\n", SYNC_LOSS_THOLD-act_ctr); + if (act_ctr >= SYNC_LOSS_THOLD) { + act_ctr = 0; + cm.sync_active = sync_active; + status = ACTIVITY_CHANGE; + } else { + act_ctr++; + } + } else { + act_ctr = 0; + } + + + data1 = tvp_readreg(TVP_LINECNT1); + data2 = tvp_readreg(TVP_LINECNT2); + totlines = ((data2 & 0x0f) << 8) | data1; + progressive = !!(data2 & (1<<5)); + cm.macrovis = !!(data2 & (1<<6)); + + fpga_totlines = IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff; + + //TODO: check flags instead + if (vsyncmode == 0x2) { + progressive = 1; + } else if ((vsyncmode == 0x1) && fpga_totlines > ((totlines-1)*2)) { + progressive = 0; + totlines = fpga_totlines; //ugly hack + } + + data1 = tvp_readreg(TVP_CLKCNT1); + data2 = tvp_readreg(TVP_CLKCNT2); + clkcnt = ((data2 & 0x0f) << 8) | data1; + + //Not fully implemented yet + /*refclk = !!(cword & TVP_CLKSEL_BIT); + refclk = 0; + + if (refclk != cm.refclk) + status = (status < REFCLK_CHANGE) ? REFCLK_CHANGE : status;*/ + + /*if (tc.tx_mode != cm.cc.tx_mode) + status = (status < TX_MODE_CHANGE) ? TX_MODE_CHANGE : status;*/ + + // TODO: avoid random sync losses? + if ((abs((alt_16)totlines - (alt_16)cm.totlines) > LINECNT_THOLD) || (clkcnt != cm.clkcnt) || (progressive != cm.progressive)) { + printf("totlines: %u (cur) / %u (prev), clkcnt: %u (cur) / %u (prev). Data1: 0x%.2x, Data2: 0x%.2x\n", (unsigned)totlines, (unsigned)cm.totlines, (unsigned)clkcnt, (unsigned)cm.clkcnt, (unsigned)data1, (unsigned)data2); + stable_frames = 0; + } else if (stable_frames != STABLE_THOLD) { + stable_frames++; + if (stable_frames == STABLE_THOLD) + status = (status < MODE_CHANGE) ? MODE_CHANGE : status; + } + + if ((tc.linemult_target != cm.cc.linemult_target) || (tc.l3_mode != cm.cc.l3_mode)) + status = (status < MODE_CHANGE) ? MODE_CHANGE : status; + + if ((tc.s480p_mode != cm.cc.s480p_mode) && (video_modes[cm.id].flags & (MODE_DTV480P|MODE_VGA480P))) + status = (status < MODE_CHANGE) ? MODE_CHANGE : status; + + cm.totlines = totlines; + cm.clkcnt = clkcnt; + cm.progressive = progressive; + + if ((tc.sl_mode != cm.cc.sl_mode) || + (tc.sl_str != cm.cc.sl_str) || + (tc.sl_id != cm.cc.sl_id) || + (tc.h_mask != cm.cc.h_mask) || + (tc.v_mask != cm.cc.v_mask)) + status = (status < INFO_CHANGE) ? INFO_CHANGE : status; + + if (tc.sampler_phase != cm.cc.sampler_phase) + tvp_set_hpll_phase(tc.sampler_phase-SAMPLER_PHASE_MIN); + + if (tc.ypbpr_cs != cm.cc.ypbpr_cs) + tvp_sel_csc(&csc_coeffs[tc.ypbpr_cs]); + + if (tc.video_lpf != cm.cc.video_lpf) + set_lpf(tc.video_lpf); + + if (tc.sync_lpf != cm.cc.sync_lpf) + tvp_set_sync_lpf(tc.sync_lpf); + + // use memcpy instead? + cm.cc = tc; + + return status; +} + +// h_info: [31:30] [29:28] [27] [26:16] [15:12] [11:8] [7:0] +// | H_LINEMULT[1:0] | H_L3MODE[1:0] | | H_ACTIVE[10:0] | | H_MASK[3:0] | H_BACKPORCH[7:0] | +// +// v_info: [31:30] [29] [26:24] [23:13] [15:10] [9:6] [5:0] +// | | V_SCANLINES | V_SCANLINEDIR | V_SCANLINEID | V_SCANLINESTR[2:0] | V_ACTIVE[10:0] | | V_MASK[3:0]| V_BACKPORCH[5:0] | +void set_videoinfo() { + alt_u8 slid_target; + + if (video_modes[cm.id].flags & MODE_L3ENABLE_MASK) { + cm.linemult = 2; + slid_target = cm.cc.sl_id ? 2 : 0; + } else if (video_modes[cm.id].flags & MODE_L2ENABLE) { + cm.linemult = 1; + slid_target = cm.cc.sl_id; + } else { + cm.linemult = 0; + slid_target = cm.cc.sl_id; + } + + IOWR_ALTERA_AVALON_PIO_DATA(PIO_2_BASE, (cm.linemult<<30) | (cm.cc.l3_mode<<28) | (video_modes[cm.id].h_active<<16) | (cm.cc.h_mask)<<8 | video_modes[cm.id].h_backporch); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, ((!!cm.cc.sl_mode)<<29) | (cm.cc.sl_mode > 0 ? (cm.cc.sl_mode-1)<<28 : 0) | (slid_target<<27) | (cm.cc.sl_str<<24) | (video_modes[cm.id].v_active<<13) | (cm.cc.v_mask<<6) | video_modes[cm.id].v_backporch); +} + +// Configure TVP7002 and scan converter logic based on the video mode +void program_mode() { + alt_u32 data1, data2; + alt_u32 h_hz, v_hz_x100; + + // Mark as stable (needed after sync up to avoid unnecessary mode switch) + stable_frames = STABLE_THOLD; + + if ((cm.clkcnt != 0) && (cm.totlines != 0)) { //prevent div by 0 + h_hz = clkrate[cm.refclk]/cm.clkcnt; + v_hz_x100 = cm.progressive ? (100*clkrate[cm.refclk]/cm.clkcnt)/cm.totlines : (2*(100*clkrate[cm.refclk]/cm.clkcnt))/cm.totlines; + } else { + h_hz = 15700; + v_hz_x100 = 6000; + } + + printf("\nLines: %u %c\n", (unsigned)cm.totlines, cm.progressive ? 'p' : 'i'); + printf("Clocks per line: %u : HS %u.%.3u kHz VS %u.%.2u Hz\n", (unsigned)cm.clkcnt, (unsigned)(h_hz/1000), (unsigned)(h_hz%1000), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100)); + + data1 = tvp_readreg(TVP_HSINWIDTH); + data2 = tvp_readreg(TVP_VSINWIDTH); + printf("Hswidth: %u Vswidth: %u Macrovision: %u\n", (unsigned)data1, (unsigned)(data2 & 0x1F), (unsigned)cm.macrovis); + + //TODO: rewrite with strncpy to reduce code size + sniprintf(row1, LCD_ROW_LEN+1, "%s %u%c", avinput_str[cm.avinput], (unsigned)cm.totlines, cm.progressive ? 'p' : 'i'); + sniprintf(row2, LCD_ROW_LEN+1, "%u.%.2ukHz %u.%.2uHz", (unsigned)(h_hz/1000), (unsigned)((h_hz%1000)/10), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100)); + //strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); + //strncpy(row2, avinput_str[cm.avinput], LCD_ROW_LEN+1); + if (!menu_active) + lcd_write_status(); + + //printf ("Get mode id with %u %u %f\n", totlines, progressive, hz); + cm.id = get_mode_id(cm.totlines, cm.progressive, v_hz_x100/100, target_typemask, cm.cc.linemult_target, cm.cc.l3_mode, cm.cc.s480p_mode); + + if ( cm.id == -1) { + printf ("Error: no suitable mode found, defaulting to 240p\n"); + cm.id = 4; + } + + target_type = target_typemask & video_modes[cm.id].type; + + printf("Mode %s selected\n", video_modes[cm.id].name); + + tvp_source_setup(cm.id, target_type, (cm.progressive ? cm.totlines : cm.totlines/2), v_hz_x100/100, cm.refclk); + set_lpf(cm.cc.video_lpf); + set_videoinfo(); +} + +inline void TX_enable(tx_mode_t mode) { + //SetAVMute(TRUE); + if (mode == TX_HDMI) { + EnableVideoOutput(PCLK_MEDIUM, COLOR_RGB444, COLOR_RGB444, 1); + HDMITX_SetAVIInfoFrame(1, F_MODE_RGB444, 0, 0); + } else { + EnableVideoOutput(PCLK_MEDIUM, COLOR_RGB444, COLOR_RGB444, 0); + } + SetAVMute(FALSE); +} + +// Initialize hardware +int init_hw() { + alt_u32 chiprev; + + // Reset error vector and scan converter + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_2_BASE, 0x00000000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, 0x00000000); + usleep(10000); + + // unreset hw + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x03); + + //wait >500ms for SD card interface to be stable + //over 200ms and LCD may be buggy? + usleep(200000); + + // IT6613 officially supports only 100kHz, but 400kHz seems to work + I2C_init(I2CA_BASE,ALT_CPU_FREQ,400000); + + /* Initialize the character display */ + lcd_init(); + + if (!ths_init()) { + printf("Error: could not read from THS7353\n"); + return -2; + } + + /* check if TVP is found */ + chiprev = tvp_readreg(TVP_CHIPREV); + //printf("chiprev %d\n", chiprev); + + if ( chiprev == 0xff) { + printf("Error: could not read from TVP7002\n"); + return -3; + } + + tvp_init(); + + chiprev = HDMITX_ReadI2C_Byte(IT_DEVICEID); + + if ( chiprev != 0x13) { + printf("Error: could not read from IT6613\n"); + return -4; + } + + InitIT6613(); + + if (check_flash() != 0) { + printf("Error: incorrect flash type detected\n"); + return -1; + } + + // safe? + read_userdata(); + + // enforce DVI mode on non-DIY boards + if ((IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & HDMITX_MODE_MASK)) { + cm.cc.tx_mode = TX_DVI; + tc.tx_mode = TX_DVI; + } + + if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PB1_MASK)) + setup_rc(); + + //enable TX (videogen) + TX_enable(cm.cc.tx_mode); + + return 0; +} + +// Enable chip outputs +void enable_outputs() { + // program video mode + program_mode(); + // enable TVP output + tvp_enable_output(); + + // enable and unmute HDMITX + // TODO: check pclk + TX_enable(cm.cc.tx_mode); +} + +int main() +{ + tvp_input_t target_input; + ths_input_t target_ths; + video_format target_format; + avinput_t target_mode; + + alt_u8 av_init = 0; + status_t status; + alt_u32 test; + + int init_stat; + + init_stat = init_hw(); + + if (init_stat >= 0) { + printf("### DIY VIDEO DIGITIZER / SCANCONVERTER INIT OK ###\n\n"); + sniprintf(row1, LCD_ROW_LEN+1, "OSSC fw. %u.%.2u", fw_ver_major, fw_ver_minor); + strncpy(row2, "2014-2015 marqs", LCD_ROW_LEN+1); + lcd_write_status(); + } else { + sniprintf(row1, LCD_ROW_LEN+1, "Init error %d", init_stat); + strncpy(row2, "", LCD_ROW_LEN+1); + lcd_write_status(); + while (1) {} + } + + while(1) { + // Select target input and mode + remote_code = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK; + btn_code = ~IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PB_MASK; + + if (remote_code_prev == 0 && remote_code != 0) + printf("RCODE: 0x%.4x\n", remote_code); + + if (btn_code_prev == 0 && btn_code != 0) + printf("BCODE: 0x%.2x\n", btn_code>>16); + + target_mode = AV_KEEP; + + if (remote_code_prev == 0) { + if (remote_code == rc_keymap[RC_BTN1]) { + if (cm.avinput == AV1_RGBs) + target_mode = AV1_RGsB; + else + target_mode = AV1_RGBs; + } else if (remote_code == rc_keymap[RC_BTN2]) { + if (cm.avinput == AV2_YPBPR) + target_mode = AV2_RGsB; + else + target_mode = AV2_YPBPR; + } else if (remote_code == rc_keymap[RC_BTN3]) { + if (cm.avinput == AV3_RGBHV) + target_mode = AV3_RGBs; + else if (cm.avinput == AV3_RGBs) + target_mode = AV3_RGsB; + else + target_mode = AV3_RGBHV; + } + } + if ((btn_code_prev == 0) && (btn_code & PB0_MASK)) { + target_mode = (cm.avinput == AV3_RGsB) ? AV1_RGBs : (cm.avinput+1); + } + + if (target_mode == cm.avinput) + target_mode = AV_KEEP; + + if (target_mode != AV_KEEP) + printf("### SWITCH MODE TO %s ###\n", avinput_str[target_mode]); + + switch (target_mode) { + case AV1_RGBs: + target_input = TVP_INPUT1; + target_format = FORMAT_RGBS; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_B; + break; + case AV1_RGsB: + target_input = TVP_INPUT1; + target_format = FORMAT_RGsB; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_B; + break; + case AV2_YPBPR: + target_input = TVP_INPUT1; + target_format = FORMAT_YPbPr; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_A; + break; + case AV2_RGsB: + target_input = TVP_INPUT1; + target_format = FORMAT_RGsB; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_INPUT_A; + break; + case AV3_RGBHV: + target_input = TVP_INPUT3; + target_format = FORMAT_RGBHV; + target_typemask = VIDEO_PC; + target_ths = THS_STANDBY; + break; + case AV3_RGBs: + target_input = TVP_INPUT3; + target_format = FORMAT_RGBS; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_STANDBY; + break; + case AV3_RGsB: + target_input = TVP_INPUT3; + target_format = FORMAT_RGsB; + target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV; + target_ths = THS_STANDBY; + break; + default: + break; + } + + if (target_mode != AV_KEEP) { + av_init = 1; + cm.avinput = target_mode; + cm.sync_active = 0; + ths_source_sel(target_ths, (cm.cc.video_lpf > 1) ? (VIDEO_LPF_MAX-cm.cc.video_lpf) : THS_LPF_BYPASS); + tvp_disable_output(); + tvp_source_sel(target_input, target_format, cm.refclk); + cm.clkcnt = 0; //TODO: proper invalidate + strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); + strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); + if (!menu_active) + lcd_write_status(); + } + + usleep(MAINLOOP_SLEEP_US); + read_control(); + + if (av_init) { + status = get_status(target_input); + + switch (status) { + case ACTIVITY_CHANGE: + if (cm.sync_active) { + printf("Sync up\n"); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) | (1<<2))); //disable videogen + enable_outputs(); + } else { + printf("Sync lost\n"); + cm.clkcnt = 0; //TODO: proper invalidate + tvp_disable_output(); + //ths_source_sel(THS_STANDBY, 0); + strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1); + strncpy(row2, " NO SYNC", LCD_ROW_LEN+1); + if (!menu_active) + lcd_write_status(); + } + break; + /*case TX_MODE_CHANGE: + if (cm.sync_active) + TX_enable(cm.cc.tx_mode); + printf("TX mode change\n"); + break;*/ + /*case REFCLK_CHANGE: + if (cm.sync_active) { + printf("Refclk change\n"); + tvp_sel_clk(cm.refclk); + } + break;*/ + case MODE_CHANGE: + if (cm.sync_active && (cm.totlines >= MIN_VALID_LINES)) { + printf("Mode change\n"); + program_mode(); + } + break; + case INFO_CHANGE: + if (cm.sync_active) { + printf("Info change\n"); + set_videoinfo(); + } + break; + default: + break; + } + } + + remote_code_prev = remote_code; + btn_code_prev = btn_code; + } + + return 0; +} diff --git a/software/sys_controller/it6613/EDID.c b/software/sys_controller/it6613/EDID.c new file mode 100644 index 0000000..647dc41 --- /dev/null +++ b/software/sys_controller/it6613/EDID.c @@ -0,0 +1,196 @@ +#include "hdmitx.h" +#include "edid.h" + +#ifdef SUPPORT_EDID +static SYS_STATUS EDIDCheckSum(BYTE *pEDID) ; + +static SYS_STATUS +EDIDCheckSum(BYTE *pEDID) +{ + BYTE CheckSum ; + int i ; + + if( !pEDID ) + { + return ER_FAIL ; + } + for( i = 0, CheckSum = 0 ; i < 128 ; i++ ) + { + CheckSum += pEDID[i] ; CheckSum &= 0xFF ; + } + + return (CheckSum == 0)?ER_SUCCESS:ER_FAIL ; +} + +SYS_STATUS +ParseVESAEDID(BYTE *pEDID) +{ + if( ER_SUCCESS != EDIDCheckSum(pEDID) ) return ER_FAIL ; + + if( pEDID[0] != 0 || + pEDID[7] != 0 || + pEDID[1] != 0xFF || + pEDID[2] != 0xFF || + pEDID[3] != 0xFF || + pEDID[4] != 0xFF || + pEDID[5] != 0xFF || + pEDID[6] != 0xFF ) + { + return ER_FAIL ; // not a EDID 1.3 standard block. + } + + ///////////////////////////////////////////////////////// + // if need to parse EDID property , put here. + ///////////////////////////////////////////////////////// + + return ER_SUCCESS ; + +} + +SYS_STATUS +ParseCEAEDID(BYTE *pCEAEDID, RX_CAP *pRxCap) +{ + BYTE offset,End ; + BYTE count ; + BYTE tag ; + int i ; + + if( !pCEAEDID || !pRxCap ) return ER_FAIL ; + + pRxCap->ValidCEA = FALSE ; + + if( ER_SUCCESS != EDIDCheckSum(pCEAEDID) ) return ER_FAIL ; + + if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) return ER_SUCCESS ; // not a CEA BLOCK. + End = pCEAEDID[2] ; // CEA description. + pRxCap->VideoMode = pCEAEDID[3] ; + + if (pRxCap->VideoMode & CEA_SUPPORT_YUV444) + OS_PRINTF("Support Color: YUV444\n"); + if (pRxCap->VideoMode & CEA_SUPPORT_YUV422) + OS_PRINTF("Support Color: YUV422\n"); + + for( offset = 0 ; offset < 0x80 ; offset ++ ) + { + if( (offset % 0x10) == 0 ) + { + ErrorF("[%02X]", offset ) ; + } + else if((offset%0x10)==0x08) + { + ErrorF( " -" ) ; + } + ErrorF(" %02X",pCEAEDID[offset]) ; + if((offset%0x10)==0x0f) + { + ErrorF("\n") ; + } + } + + pRxCap->VDOModeCount = 0 ; + pRxCap->idxNativeVDOMode = 0xff ; + for( offset = 4 ; offset < End ; ) + { + tag = pCEAEDID[offset] >> 5 ; + count = pCEAEDID[offset] & 0x1f ; + switch( tag ) + { + case 0x01: // Audio Data Block ; + pRxCap->AUDDesCount = count/3 ; + offset++ ; + for( i = 0 ; i < pRxCap->AUDDesCount ; i++ ) + { + pRxCap->AUDDes[i].uc[0] = pCEAEDID[offset++] ; + pRxCap->AUDDes[i].uc[1] = pCEAEDID[offset++] ; + pRxCap->AUDDes[i].uc[2] = pCEAEDID[offset++] ; + + } + + break ; + + case 0x02: // Video Data Block ; + //pRxCap->VDOModeCount = 0 ; + offset ++ ; + for( i = 0,pRxCap->idxNativeVDOMode = 0xff ; i < count ; i++, offset++ ) + { + BYTE VIC ; + VIC = pCEAEDID[offset] & (~0x80) ; + OS_PRINTF("HDMI Sink VIC(Video Identify Code)=%d\n", VIC); + // if( FindModeTableEntryByVIC(VIC) != -1 ) + { + pRxCap->VDOMode[pRxCap->VDOModeCount] = VIC ; + if( pCEAEDID[offset] & 0x80 ) + { + pRxCap->idxNativeVDOMode = (BYTE)pRxCap->VDOModeCount ; + // iVideoModeSelect = pRxCap->VDOModeCount ; + } + + pRxCap->VDOModeCount++ ; + } + } + break ; + case 0x03: // Vendor Specific Data Block ; + offset ++ ; + pRxCap->IEEEOUI = (ULONG)pCEAEDID[offset+2] ; + pRxCap->IEEEOUI <<= 8 ; + pRxCap->IEEEOUI += (ULONG)pCEAEDID[offset+1] ; + pRxCap->IEEEOUI <<= 8 ; + pRxCap->IEEEOUI += (ULONG)pCEAEDID[offset] ; + + /////////////////////////////////////////////////////////// + // For HDMI 1.3 extension handling. + /////////////////////////////////////////////////////////// + + pRxCap->dc.uc = 0 ; + pRxCap->MaxTMDSClock = 0 ; + pRxCap->lsupport.uc = 0 ; + pRxCap->ValidHDMI = (pRxCap->IEEEOUI==HDMI_IEEEOUI)? TRUE:FALSE ; + if( (pRxCap->ValidHDMI) && (count > 5 )) + { + // HDMI 1.3 extension + pRxCap->dc.uc = pCEAEDID[offset+5] ; + pRxCap->MaxTMDSClock = pCEAEDID[offset+6] ; + pRxCap->lsupport.uc = pCEAEDID[offset+7] ; + + if(pRxCap->lsupport.info.Latency_Present) + { + pRxCap->V_Latency = pCEAEDID[offset+9] ; + pRxCap->A_Latency = pCEAEDID[offset+10] ; + } + + if(pRxCap->lsupport.info.I_Latency_Present) + { + pRxCap->V_I_Latency = pCEAEDID[offset+11] ; + pRxCap->A_I_Latency = pCEAEDID[offset+12] ; + } + + } + + offset += count ; // ignore the remaind. + break ; + + case 0x04: // Speaker Data Block ; + offset ++ ; + pRxCap->SpeakerAllocBlk.uc[0] = pCEAEDID[offset] ; + pRxCap->SpeakerAllocBlk.uc[1] = pCEAEDID[offset+1] ; + pRxCap->SpeakerAllocBlk.uc[2] = pCEAEDID[offset+2] ; + offset += 3 ; + break ; + case 0x05: // VESA Data Block ; + offset += count+1 ; + break ; + case 0x07: // Extended Data Block ; + offset += count+1 ; //ignore + break ; + default: + offset += count+1 ; // ignore + } + } + + pRxCap->ValidCEA = TRUE ; + return ER_SUCCESS ; +} + + + +#endif // SUPPORT_EDID diff --git a/software/sys_controller/it6613/HDMI_COMMON.h b/software/sys_controller/it6613/HDMI_COMMON.h new file mode 100644 index 0000000..47b77cc --- /dev/null +++ b/software/sys_controller/it6613/HDMI_COMMON.h @@ -0,0 +1,11 @@ +#ifndef HDMI_COMMON_H_ +#define HDMI_COMMON_H_ + +typedef enum{ + COLOR_RGB444 = 0, + COLOR_YUV422, + COLOR_YUV444, + COLOR_MODE_NUM +}COLOR_TYPE; + +#endif /*HDMI_COMMON_H_*/ diff --git a/software/sys_controller/it6613/HDMI_TX.c b/software/sys_controller/it6613/HDMI_TX.c new file mode 100644 index 0000000..580ee50 --- /dev/null +++ b/software/sys_controller/it6613/HDMI_TX.c @@ -0,0 +1,314 @@ +//#include "terasic_includes.h" +//#include "mcu.h" +#include "it6613_sys.h" +#include "hdmitx.h" +#include "HDMI_TX.h" +#include "edid.h" + + +int TX_HDP = FALSE; +extern BYTE bOutputColorMode; +extern BYTE bInputColorMode; +extern BOOL bChangeMode; +extern RX_CAP RxCapability; +extern BOOL bHDMIMode; +extern BOOL bAudioEnable; +BOOL ParseEDID(); + +INSTANCE InitInstanceData = +{ + 0,0, //I2C_DEV, I2C_ADDR + 0, //bIntType (TxCLK active, Push-Pull Mode, INT active low) + 0,/* | T_MODE_CCIR656 | T_MODE_SYNCEMB | T_MODE_INDDR */ // bInputVideoSignalType + + B_AUDFMT_STD_I2S, // bOutputAudioMode, 0x00, standard i2s, rising edge to sample ws/i2s, not full packet mode REG[0xE1] + + 0,// bAudioChannelSwap + B_AUD_EN_I2S0 | B_AUD_I2S | M_AUD_16BIT, // bAudioChannelEnable, 0x01, REG[0xE0], defined in it6613_drv.h + AUDFS_48KHz, //0, //bAudFs, + 0, // TMDSClock + TRUE,//bAuthenticated + TRUE,// bHDMIMode + FALSE,// bIntPOL + FALSE // bHPD +} ; + +bool HDMITX_ChipVerify(void){ + bool bPass = FALSE; + alt_u8 szID[4]; + int i; + + + for(i=0;i<4;i++) + szID[i] = HDMITX_ReadI2C_Byte(i); + +// if (szID[0] == 0x00 && szID[1] == 0xCA && szID[1] == 0x13 && szID[1] == 0x06) szID[0] ??? + if ((szID[1] == 0xCA && szID[2] == 0x13 && szID[3] == 0x06) || (szID[1] == 0xCA && szID[2] == 0x13 && szID[3] == 0x16)){ + bPass = TRUE; + printf("TX Chip Revision ID: %d\n", szID[0]); + }else{ + printf("NG, Read TX Chip ID:%02X%02X%02X%02Xh (expected:00CA1306h)\n", szID[0], szID[1], szID[2], szID[3]); + } + + return bPass; +} + +bool HDMITX_Init(void){ + bool bSuccess = TRUE; + HDMITX_Reset(); + usleep(500*1000); + if (!HDMITX_ChipVerify()){ + OS_PRINTF("Failed to find IT6613 HDMI-TX Chip.\n"); + bSuccess = FALSE; + //return 0; + } + + HDMITX_InitInstance(&InitInstanceData) ; + InitIT6613() ; + + + return bSuccess; +} + +bool HDMITX_HPD(void){ + if (TX_HDP) + return TRUE; + return FALSE; +} + + +void HDMITX_SetAVIInfoFrame(alt_u8 VIC, alt_u8 OutputColorMode, bool b16x9, bool ITU709) +{ + AVI_InfoFrame AviInfo; + alt_u8 pixelrep = 0; + + OS_PRINTF("HDMITX_SetAVIInfoFrame, VIC=%d, ColorMode=%d, Aspect-Ratio=%s, ITU709=%s\n", + VIC, OutputColorMode, b16x9?"16:9":"4:3", ITU709?"Yes":"No"); + + AviInfo.pktbyte.AVI_HB[0] = AVI_INFOFRAME_TYPE|0x80 ; + AviInfo.pktbyte.AVI_HB[1] = AVI_INFOFRAME_VER ; + AviInfo.pktbyte.AVI_HB[2] = AVI_INFOFRAME_LEN ; + + switch(OutputColorMode) + { + case F_MODE_YUV444: + // AviInfo.info.ColorMode = 2 ; + AviInfo.pktbyte.AVI_DB[0] = (2<<5)|(1<<4) ; + break ; + case F_MODE_YUV422: + // AviInfo.info.ColorMode = 1 ; + AviInfo.pktbyte.AVI_DB[0] = (1<<5)|(1<<4) ; + break ; + case F_MODE_RGB444: + default: + // AviInfo.info.ColorMode = 0 ; + AviInfo.pktbyte.AVI_DB[0] = (0<<5)|(1<<4) ; + break ; + } + AviInfo.pktbyte.AVI_DB[0] |= 2; // indicate "no overscan" + AviInfo.pktbyte.AVI_DB[1] = 8 ; + AviInfo.pktbyte.AVI_DB[1] |= (!b16x9)?(1<<4):(2<<4) ; // 4:3 or 16:9 + AviInfo.pktbyte.AVI_DB[1] |= (!ITU709)?(1<<6):(2<<6) ; // ITU709 or ITU601 + AviInfo.pktbyte.AVI_DB[2] = (1<<3) ; // indicate "full-range RGB" + AviInfo.pktbyte.AVI_DB[3] = VIC ; + AviInfo.pktbyte.AVI_DB[4] = pixelrep & 3 ; + AviInfo.pktbyte.AVI_DB[5] = 0 ; + AviInfo.pktbyte.AVI_DB[6] = 0 ; + AviInfo.pktbyte.AVI_DB[7] = 0 ; + AviInfo.pktbyte.AVI_DB[8] = 0 ; + AviInfo.pktbyte.AVI_DB[9] = 0 ; + AviInfo.pktbyte.AVI_DB[10] = 0 ; + AviInfo.pktbyte.AVI_DB[11] = 0 ; + AviInfo.pktbyte.AVI_DB[12] = 0 ; + + EnableAVIInfoFrame(TRUE, (unsigned char *)&AviInfo) ; +} + +void HDMITX_ChangeVideoTiming(int VIC){ + int OutputVideoTiming = VIC; + int HdmiColorMode; + + switch(bOutputColorMode) + { + case F_MODE_YUV444: + HdmiColorMode = HDMI_YUV444; + break ; + case F_MODE_YUV422: + HdmiColorMode = HDMI_YUV422; + break ; + case F_MODE_RGB444: + default: + HdmiColorMode = HDMI_RGB444; + break ; + } + + HDMITX_ChangeDisplayOption(OutputVideoTiming, HdmiColorMode); // just modify variable. Take effect when HDMITX_SetOutput is called in HDMITX_DevLoopProc +} + +void HDMITX_ChangeVideoTimingAndColor(int VIC, COLOR_TYPE Color){ + int OutputVideoTiming = VIC; + int HdmiColorMode; + + switch(Color) + { + case COLOR_YUV444: + HdmiColorMode = HDMI_YUV444; + break ; + case COLOR_YUV422: + HdmiColorMode = HDMI_YUV422; + break ; + case COLOR_RGB444: + default: + HdmiColorMode = HDMI_RGB444; + break ; + } + HDMITX_ChangeDisplayOption(OutputVideoTiming, HdmiColorMode); +} + +void HDMITX_DisableVideoOutput(void){ + DisableVideoOutput(); +} + +void HDMITX_EnableVideoOutput(void){ + HDMITX_SetOutput(); +} + +void HDMITX_SetColorSpace(COLOR_TYPE InputColor, COLOR_TYPE OutputColor){ + // DisableVideoOutput(); + bInputColorMode = InputColor; + bOutputColorMode = OutputColor; + // HDMITX_SetOutput(); +} + +bool HDMITX_IsSinkSupportYUV444(void){ + bool bSupport = FALSE; + if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA && + (RxCapability.VideoMode & CEA_SUPPORT_YUV444)) + bSupport = TRUE; + return bSupport; +} + +bool HDMITX_IsSinkSupportYUV422(void){ + bool bSupport = FALSE; + if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA && + (RxCapability.VideoMode & CEA_SUPPORT_YUV422)) + bSupport = TRUE; + return bSupport; +} + +bool HDMITX_IsSinkSupportColorDepth36(void){ + bool bSupport = FALSE; + if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA && + RxCapability.dc.info.DC_36Bit) + bSupport = TRUE; + return bSupport; +} + + +bool HDMITX_IsSinkSupportColorDepth30(void){ + bool bSupport = FALSE; + if (RxCapability.Valid && RxCapability.ValidHDMI && RxCapability.ValidCEA && + RxCapability.dc.info.DC_30Bit) + bSupport = TRUE; + return bSupport; +} + +void HDMITX_SetOutputColorDepth(int ColorDepth){ + SetOutputColorDepthPhase(ColorDepth, 0); +} + + + +bool HDMITX_DevLoopProc() +{ + static BYTE PreHPDChange = 0; + static BYTE PreHPD = 0; + BYTE HPD, HPDChange ; + + // Richard CheckHDMI(&HPD,&HPDChange) ; + CheckHDMITX(&HPD,&HPDChange) ; + + if (HPD == PreHPD && HPDChange) // richard add + return FALSE; + + TX_HDP = HPD; + PreHPD = HPD; + PreHPDChange = HPDChange; + + if( HPDChange ) + { + + + OS_PRINTF("HPDChange\n"); + if( HPD ) + { + OS_PRINTF("HPD=ON\n"); + RxCapability.Valid = ParseEDID() ; + //bOutputColorMode = F_MODE_YUV444; //F_MODE_RGB444; // richard node. users can change color space here according to HDMI sink + + if( RxCapability.Valid && RxCapability.ValidHDMI ) + { + OS_PRINTF("HDMI Display found\n"); + bHDMIMode = TRUE ; + + if(RxCapability.VideoMode & (1<<6)) + { + bAudioEnable = TRUE ; + } + +#if 0 // richard, don't care edid, the output always RGB444 + if( RxCapability.VideoMode & (1<<5)) + { + bOutputColorMode &= ~F_MODE_CLRMOD_MASK ; + bOutputColorMode |= F_MODE_YUV444; + } + else if (RxCapability.VideoMode & (1<<4)) + { + bOutputColorMode &= ~F_MODE_CLRMOD_MASK ; + bOutputColorMode |= F_MODE_YUV422 ; + } +#endif + } + else if (!RxCapability.Valid) + { + OS_PRINTF("Failed to read EDID\n"); + + // enable it when edid fail + bHDMIMode = TRUE ; + bAudioEnable = TRUE ; + } + else + { + OS_PRINTF("Invalid HDMI Display\n"); + bHDMIMode = FALSE ; + bAudioEnable = FALSE ; + } + + OS_PRINTF("HDMITX_SetOutput\n"); + //HDMITX_SetOutput() ; + + } + else + { + OS_PRINTF("HPD=OFF\n"); + // unplug mode, ... + OS_PRINTF("DisableVideoOutput\n"); + //DisableVideoOutput() ; + RxCapability.Valid = FALSE; // richard add + RxCapability.ValidHDMI = FALSE; // richard add + RxCapability.ValidCEA = FALSE; // richard add + } + } + else // no stable but need to process mode change procedure + { + if(bChangeMode && HPD) + { + OS_PRINTF("HDMITX_SetOutput\n"); + HDMITX_SetOutput() ; + } + } + + return HPDChange; +} + + diff --git a/software/sys_controller/it6613/HDMI_TX.h b/software/sys_controller/it6613/HDMI_TX.h new file mode 100644 index 0000000..65b9ad9 --- /dev/null +++ b/software/sys_controller/it6613/HDMI_TX.h @@ -0,0 +1,29 @@ +#ifndef HDMI_TX_H_ +#define HDMI_TX_H_ + +#include "HDMI_COMMON.h" +#include "alt_types.h" +#include "hdmitx.h" + + + +bool HDMITX_Init(void); +bool HDMITX_ChipVerify(void); +bool HDMITX_HPD(void); +void HDMITX_ChangeVideoTiming(int VIC); +void HDMITX_ChangeVideoTimingAndColor(int VIC, COLOR_TYPE Color); +void HDMITX_SetAVIInfoFrame(alt_u8 VIC, alt_u8 OutputColorMode, bool b16x9, bool ITU709); + +void HDMITX_DisableVideoOutput(void); +void HDMITX_EnableVideoOutput(void); +void HDMITX_SetColorSpace(COLOR_TYPE InputColor, COLOR_TYPE OutputColor); +bool HDMITX_DevLoopProc(void); + +bool HDMITX_IsSinkSupportYUV444(void); +bool HDMITX_IsSinkSupportYUV422(void); + +bool HDMITX_IsSinkSupportColorDepth36(void); +bool HDMITX_IsSinkSupportColorDepth30(void); +void HDMITX_SetOutputColorDepth(int ColorDepth); + +#endif /*HDMI_TX_H_*/ diff --git a/software/sys_controller/it6613/edid.h b/software/sys_controller/it6613/edid.h new file mode 100644 index 0000000..24c16b4 --- /dev/null +++ b/software/sys_controller/it6613/edid.h @@ -0,0 +1,129 @@ +#ifndef _EDID_H_ +#define _EDID_H_ + +#include "hdmitx.h" + +#ifdef SUPPORT_EDID + +///////////////////////////////////////// +// RX Capability. +///////////////////////////////////////// +typedef struct { + BYTE b16bit:1 ; + BYTE b20bit:1 ; + BYTE b24bit:1 ; + BYTE Rsrv:5 ; +} LPCM_BitWidth ; + +typedef enum { + AUD_RESERVED_0 = 0 , + AUD_LPCM, + AUD_AC3, + AUD_MPEG1, + AUD_MP3, + AUD_MPEG2, + AUD_AAC, + AUD_DTS, + AUD_ATRAC, + AUD_ONE_BIT_AUDIO, + AUD_DOLBY_DIGITAL_PLUS, + AUD_DTS_HD, + AUD_MAT_MLP, + AUD_DST, + AUD_WMA_PRO, + AUD_RESERVED_15 +} AUDIO_FORMAT_CODE ; + +typedef union { + struct { + BYTE channel:3 ; + BYTE AudioFormatCode:4 ; + BYTE Rsrv1:1 ; + + BYTE b32KHz:1 ; + BYTE b44_1KHz:1 ; + BYTE b48KHz:1 ; + BYTE b88_2KHz:1 ; + BYTE b96KHz:1 ; + BYTE b176_4KHz:1 ; + BYTE b192KHz:1 ; + BYTE Rsrv2:1 ; + BYTE ucCode ; + } s ; + BYTE uc[3] ; + +} AUDDESCRIPTOR ; + +typedef union { + struct { + BYTE FL_FR:1 ; + BYTE LFE:1 ; + BYTE FC:1 ; + BYTE RL_RR:1 ; + BYTE RC:1 ; + BYTE FLC_FRC:1 ; + BYTE RLC_RRC:1 ; + BYTE Reserve:1 ; + BYTE Unuse[2] ; + } s ; + BYTE uc[3] ; +} SPK_ALLOC ; + +#define CEA_SUPPORT_UNDERSCAN (1<<7) +#define CEA_SUPPORT_AUDIO (1<<6) +#define CEA_SUPPORT_YUV444 (1<<5) +#define CEA_SUPPORT_YUV422 (1<<4) +#define CEA_NATIVE_MASK 0xF + +typedef union _tag_DCSUPPORT { + struct { + BYTE DVI_Dual:1 ; + BYTE Rsvd:2 ; + BYTE DC_Y444:1 ; + BYTE DC_30Bit:1 ; + BYTE DC_36Bit:1 ; + BYTE DC_48Bit:1 ; + BYTE SUPPORT_AI:1 ; + } info ; + BYTE uc ; +} DCSUPPORT ; // Richard Note: Color Depth + +typedef union _LATENCY_SUPPORT{ + struct { + BYTE Rsvd:6 ; + BYTE I_Latency_Present:1 ; + BYTE Latency_Present:1 ; + } info ; + BYTE uc ; +} LATENCY_SUPPORT ; + +#define HDMI_IEEEOUI 0x0c03 + +typedef struct _RX_CAP{ + BYTE Valid; // richard add + BYTE VideoMode ; + BYTE VDOModeCount ; + BYTE idxNativeVDOMode ; + BYTE VDOMode[128] ; + BYTE AUDDesCount ; + AUDDESCRIPTOR AUDDes[32] ; + ULONG IEEEOUI ; + DCSUPPORT dc ; + BYTE MaxTMDSClock ; + LATENCY_SUPPORT lsupport ; + BYTE V_Latency ; + BYTE A_Latency ; + BYTE V_I_Latency ; + BYTE A_I_Latency ; + SPK_ALLOC SpeakerAllocBlk ; + BYTE ValidCEA:1 ; + BYTE ValidHDMI:1 ; +} RX_CAP ; + +SYS_STATUS ParseVESAEDID(BYTE *pEDID) ; +SYS_STATUS ParseCEAEDID(BYTE *pCEAEDID, RX_CAP *pRxCap) ; + + + +#endif // SUPPORT_EDID +#endif // _EDID_H_ diff --git a/software/sys_controller/it6613/hdmitx.h b/software/sys_controller/it6613/hdmitx.h new file mode 100644 index 0000000..fa4c45e --- /dev/null +++ b/software/sys_controller/it6613/hdmitx.h @@ -0,0 +1,119 @@ +#ifndef _HDMITX_H_ +#define _HDMITX_H_ + +#ifdef EXTERN_HDCPROM +#pragma message("Defined EXTERN_HDCPROM") +#endif // EXTERN_HDCPROM + +#define SUPPORT_EDID +//#define SUPPORT_HDCP +#define SUPPORT_INPUTRGB +//#define SUPPORT_INPUTYUV444 +//#define SUPPORT_INPUTYUV422 +//#define SUPPORT_SYNCEMBEDDED +//#define SUPPORT_DEGEN +//#define SUPPORT_INPUTYUV // richard add +//#define INVERT_VID_LATCHEDGE //latch at falling edge + + +#ifdef SUPPORT_SYNCEMBEDDED +#pragma message("defined SUPPORT_SYNCEMBEDDED for Sync Embedded timing input or CCIR656 input.") +#endif + +#ifndef _MCU_ // DSSSHA need large computation data rather than 8051 supported. +#define SUPPORT_DSSSHA +#endif + +#if defined(SUPPORT_INPUTYUV444) || defined(SUPPORT_INPUTYUV422) +#define SUPPORT_INPUTYUV +#endif + +/*#ifdef _MCU_ + #include "mcu.h" +#else // not MCU + #include + #include + #include + #include + #include + #include + #include "ioaccess.h" + #include "install.h" + #include "pc.h" +#endif // MCU*/ + +#include "typedef.h" +#include "HDMI_COMMON.h" +/*typedef unsigned char BYTE; +#define _CODE const +#define SYS_STATUS unsigned int +#define TRUE 1 +#define FALSE 0*/ +//#define NULL 0 + +//typedef unsigned char bool; +#include "Altera_UP_SD_Card_Avalon_Interface_mod.h" +#include "sysconfig.h" + +// Hardwired to CPU reset +#define HDMITX_Reset(x) + +#ifndef SUPPORT_HDCP +static SYS_STATUS +HDCP_Authenticate() +{ + return ER_SUCCESS; +} + +static void +HDCP_ResetAuth() +{ + return; +} + +static void +HDCP_ResumeAuthentication() +{ + return; +} +#endif + +//#include "edid.h" +// #include "dss_sha.h" +#include "it6613_drv.h" + +#define HDMITX_INSTANCE_MAX 1 + +#define SIZEOF_CSCMTX 18 +#define SIZEOF_CSCGAIN 6 +#define SIZEOF_CSCOFFSET 3 + +/////////////////////////////////////////////////////////////////////// +// Output Mode Type +/////////////////////////////////////////////////////////////////////// + +#define RES_ASPEC_4x3 0 +#define RES_ASPEC_16x9 1 +#define F_MODE_REPT_NO 0 +#define F_MODE_REPT_TWICE 1 +#define F_MODE_REPT_QUATRO 3 +#define F_MODE_CSC_ITU601 0 +#define F_MODE_CSC_ITU709 1 + +/////////////////////////////////////////////////////////////////////// +// ROM OFFSET +/////////////////////////////////////////////////////////////////////// +#define ROMOFF_INT_TYPE 0 +#define ROMOFF_INPUT_VIDEO_TYPE 1 +#define ROMOFF_OUTPUT_AUDIO_MODE 8 +#define ROMOFF_AUDIO_CH_SWAP 9 + + + +#define TIMER_LOOP_LEN 10 +#define MS(x) (((x)+(TIMER_LOOP_LEN-1))/TIMER_LOOP_LEN) ; // for timer loop + + + +#endif // _HDMITX_H_ + diff --git a/software/sys_controller/it6613/hdmitx_nios2.c b/software/sys_controller/it6613/hdmitx_nios2.c new file mode 100644 index 0000000..4ae9f7f --- /dev/null +++ b/software/sys_controller/it6613/hdmitx_nios2.c @@ -0,0 +1,82 @@ +#include +#include +#include "system.h" +#include "i2c_opencores.h" +#include "hdmitx.h" +#include "it6613.h" + +inline alt_u32 read_it2(alt_u32 regaddr) { + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 0); + I2C_start(I2CA_BASE, IT_BASE, 1); + return I2C_read(I2CA_BASE,1); +} + +inline void write_it2(alt_u32 regaddr, alt_u8 data) { + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 0); + I2C_write(I2CA_BASE, data, 1); +} + +BYTE I2C_Read_Byte(BYTE Addr,BYTE RegAddr) { + I2C_start(I2CA_BASE, Addr, 0); + I2C_write(I2CA_BASE, RegAddr, 0); + I2C_start(I2CA_BASE, Addr, 1); + return I2C_read(I2CA_BASE,1); +} + +SYS_STATUS I2C_Write_Byte(BYTE Addr,BYTE RegAddr,BYTE Data) { + I2C_start(I2CA_BASE, Addr, 0); + I2C_write(I2CA_BASE, RegAddr, 0); + I2C_write(I2CA_BASE, Data, 1); + return 0; +} + +SYS_STATUS I2C_Read_ByteN(BYTE Addr,BYTE RegAddr,BYTE *pData,int N) { + int i; + + for (i=0; i +#include +#include "system.h" +#include "i2c_opencores.h" +#include "it6613.h" + +volatile alt_u8 cur_bank; + +inline void select_bank_it(alt_u8 bank) { + cur_bank = bank; + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, IT_CURBANK, 0); + I2C_write(I2CA_BASE, cur_bank, 1); +} + +inline alt_u32 read_it(alt_u32 regaddr) { + if ((regaddr > 0xFF) && (cur_bank == 0)) + select_bank_it(1); + else if ((regaddr <= 0xFF) && (cur_bank == 1)) + select_bank_it(0); + + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, (regaddr & 0xFF), 1); + I2C_start(I2CA_BASE, IT_BASE, 1); + return I2C_read(I2CA_BASE,1); +} + +inline void write_it(alt_u32 regaddr, alt_u8 data) { + if ((regaddr > 0xFF) && (cur_bank == 0)) + select_bank_it(1); + else if ((regaddr <= 0xFF) && (cur_bank == 1)) + select_bank_it(0); + + I2C_start(I2CA_BASE, IT_BASE, 0); + I2C_write(I2CA_BASE, (regaddr & 0xFF), 0); + I2C_write(I2CA_BASE, data, 1); +} + +/*inline void reset_it() { + usleep(100000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); + usleep(100000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01); + usleep(100000); +}*/ + +int init_it() { + alt_u32 vendor_id, device_id; + alt_u32 i; + + cur_bank = 0; + select_bank_it(cur_bank); + + vendor_id = read_it(IT_VENDORID); + device_id = read_it(IT_DEVICEID); + + printf("VEN: 0x%.2X, DEV: 0x%.2X\n", vendor_id, device_id); + + if (!((vendor_id == IT6613_VENDORID) && (device_id == IT6613_DEVICEID))) + return -1; + + write_it(REG_TX_SW_RST,B_REF_RST|B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + usleep(1000); + write_it(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + + write_it(IT_DRIVECTRL, 0x10); + + write_it(IT_HDMIMODE, 0); + for (i=0xC1; i<=0xD0; i++) + write_it(i, 0); + + write_it(IT_OUTCOLOR, 0); + + // enable video + //HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + + write_it(REG_TX_SW_RST, B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + usleep(1000); + + + + return 0; +} diff --git a/software/sys_controller/it6613/it6613.h b/software/sys_controller/it6613/it6613.h new file mode 100644 index 0000000..89b5286 --- /dev/null +++ b/software/sys_controller/it6613/it6613.h @@ -0,0 +1,29 @@ +#ifndef IT6613_H_ +#define IT6613_H_ + +//#define I2C_DEBUG +//#define I2CA_HDMI_BASE I2C_OPENCORES_1_BASE +#define I2CA_BASE I2C_OPENCORES_0_BASE + +#define IT6613_VENDORID 0xCA +#define IT6613_DEVICEID 0x13 + +#define IT_BASE (0x98>>1) +#define IT_VENDORID 0x01 +#define IT_DEVICEID 0x02 +#define IT_RESET 0x04 +#define IT_CURBANK 0x0F +#define IT_DRIVECTRL 0x61 +#define IT_HDMIMODE 0xC0 +#define IT_OUTCOLOR 0x158 + +#define REG_TX_SW_RST 0x04 + #define B_ENTEST (1<<7) + #define B_REF_RST (1<<5) + #define B_AREF_RST (1<<4) + #define B_VID_RST (1<<3) + #define B_AUD_RST (1<<2) + #define B_HDMI_RST (1<<1) + #define B_HDCP_RST (1<<0) + +#endif /* IT6613_H_ */ diff --git a/software/sys_controller/it6613/it6613_drv.c b/software/sys_controller/it6613/it6613_drv.c new file mode 100644 index 0000000..4920ce0 --- /dev/null +++ b/software/sys_controller/it6613/it6613_drv.c @@ -0,0 +1,3461 @@ +///////////////////////////////////////////////////////////////////// +// IT6613.C +// Driver code for platform independent +///////////////////////////////////////////////////////////////////// +#include "hdmitx.h" +//#include "dss_sha.h" + +#define MSCOUNT 1000 +#define LOADING_UPDATE_TIMEOUT (3000/32) // 3sec +// USHORT u8msTimer = 0 ; +// USHORT TimerServF = TRUE ; + + + +////////////////////////////////////////////////////////////////////// +// Authentication status +////////////////////////////////////////////////////////////////////// + +// #define TIMEOUT_WAIT_AUTH MS(2000) + +#define Switch_HDMITX_Bank(x) HDMITX_WriteI2C_Byte(0x0f,(x)&1) + +#define HDMITX_OrREG_Byte(reg,ormask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) | (ormask))) +#define HDMITX_AndREG_Byte(reg,andmask) HDMITX_WriteI2C_Byte(reg,(HDMITX_ReadI2C_Byte(reg) & (andmask))) +#define HDMITX_SetREG_Byte(reg,andmask,ormask) HDMITX_WriteI2C_Byte(reg,((HDMITX_ReadI2C_Byte(reg) & (andmask))|(ormask))) + +////////////////////////////////////////////////////////////////////// +// General global variables +////////////////////////////////////////////////////////////////////// +// static _IDATA TXVideo_State_Type VState ; +// static _IDATA TXAudio_State_Type AState ; +// static _XDATA MODE_DESCRIPTION ModeID = MODE_InvalidMode; + +// BYTE I2C_DEV ; +// BYTE I2C_ADDR ; +////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////// +// // Interrupt Type +// ///////////////////////////////////////////////// +// BYTE bIntType = 0 ; +// ///////////////////////////////////////////////// +// // Video Property +// ///////////////////////////////////////////////// +// BYTE bInputVideoMode ; +// BYTE bOutputVideoMode ; +// BYTE Instance[0].bInputVideoSignalType = 0 /* | T_MODE_CCIR656 | T_MODE_SYNCEMB | T_MODE_INDDR */ ; // for Sync Embedded,CCIR656,InputDDR +// BOOL Instance[0].bAuthenticated = FALSE ; +// ///////////////////////////////////////////////// +// // Video Property +// ///////////////////////////////////////////////// +// BYTE bOutputAudioMode = 0 ; +// BYTE bAudioChannelSwap = 0 ; +////////////////////////////////////////////////////////////////////// +// BOOL Instance[0].bHDMIMode = FALSE; +// BOOL Instance[0].bIntPOL = FALSE ; // 0 = Low Active +// BOOL bHPD ; + +INSTANCE Instance[HDMITX_INSTANCE_MAX] ; + +////////////////////////////////////////////////////////////////////// +// Function Prototype +////////////////////////////////////////////////////////////////////// + +// static BOOL IsRxSense() ; + +static void SetInputMode(BYTE InputMode,BYTE bInputSignalType) ; +static void SetCSCScale(BYTE bInputMode,BYTE bOutputMode) ; +// static void SetupAFE(BYTE ucFreqInMHz) ; +static void SetupAFE(VIDEOPCLKLEVEL PCLKLevel) ; +static void FireAFE() ; + + +static SYS_STATUS SetAudioFormat(BYTE NumChannel,BYTE AudioEnable,BYTE bSampleFreq,BYTE AudSWL,BYTE AudioCatCode) ; +static SYS_STATUS SetNCTS(ULONG PCLK,ULONG Fs) ; + +static void AutoAdjustAudio() ; +static void SetupAudioChannel() ; + +static SYS_STATUS SetAVIInfoFrame(AVI_InfoFrame *pAVIInfoFrame) ; +static SYS_STATUS SetAudioInfoFrame(Audio_InfoFrame *pAudioInfoFrame) ; +static SYS_STATUS SetSPDInfoFrame(SPD_InfoFrame *pSPDInfoFrame) ; +static SYS_STATUS SetMPEGInfoFrame(MPEG_InfoFrame *pMPGInfoFrame) ; +static SYS_STATUS ReadEDID(BYTE *pData,BYTE bSegment,BYTE offset,SHORT Count) ; +static void AbortDDC() ; +static void ClearDDCFIFO() ; +static void ClearDDCFIFO() ; +static void GenerateDDCSCLK() ; +static SYS_STATUS HDCP_EnableEncryption() ; +static void HDCP_ResetAuth() ; +static void HDCP_Auth_Fire() ; +static void HDCP_StartAnCipher() ; +static void HDCP_StopAnCipher() ; +static void HDCP_GenerateAn() ; +// RICHARD static SYS_STATUS HDCP_GetVr(ULONG *pVr) ; +static SYS_STATUS HDCP_GetBCaps(PBYTE pBCaps ,PUSHORT pBStatus) ; +static SYS_STATUS HDCP_GetBKSV(BYTE *pBKSV) ; +static SYS_STATUS HDCP_Authenticate() ; +static SYS_STATUS HDCP_Authenticate_Repeater() ; +static SYS_STATUS HDCP_VerifyIntegration() ; +static SYS_STATUS HDCP_GetKSVList(BYTE *pKSVList,BYTE cDownStream) ; +static SYS_STATUS HDCP_CheckSHA(BYTE M0[],USHORT BStatus,BYTE KSVList[],int devno,BYTE Vr[]) ; +static void HDCP_ResumeAuthentication() ; +static void HDCP_Reset() ; + + +static void ENABLE_NULL_PKT() ; +static void ENABLE_ACP_PKT() ; +static void ENABLE_ISRC1_PKT() ; +static void ENABLE_ISRC2_PKT() ; +static void ENABLE_AVI_INFOFRM_PKT() ; +static void ENABLE_AUD_INFOFRM_PKT() ; +static void ENABLE_SPD_INFOFRM_PKT() ; +static void ENABLE_MPG_INFOFRM_PKT() ; + +static void DISABLE_NULL_PKT() ; +static void DISABLE_ACP_PKT() ; +static void DISABLE_ISRC1_PKT() ; +static void DISABLE_ISRC2_PKT() ; +static void DISABLE_AVI_INFOFRM_PKT() ; +static void DISABLE_AUD_INFOFRM_PKT() ; +static void DISABLE_SPD_INFOFRM_PKT() ; +static void DISABLE_MPG_INFOFRM_PKT() ; +static BYTE countbit(BYTE b) ; + +#ifdef HDMITX_REG_DEBUG +static void DumpCatHDMITXReg() ; +#endif // DEBUG + + + + + +////////////////////////////////////////////////////////////////////// +// Function Body. +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +// utility function for main.. +////////////////////////////////////////////////////////////////////// + + + +// int aiNonCEAVIC[] = { 2 } ; + +// Y,C,RGB offset +// for register 73~75 +static _CODE BYTE bCSCOffset_16_235[] = +{ + 0x00,0x80,0x00 +}; + +static _CODE BYTE bCSCOffset_0_255[] = +{ + 0x10,0x80,0x10 +}; + +#ifdef SUPPORT_INPUTRGB + static _CODE BYTE bCSCMtx_RGB2YUV_ITU601_16_235[] = + { + 0xB2,0x04,0x64,0x02,0xE9,0x00, + 0x93,0x3C,0x16,0x04,0x56,0x3F, + 0x49,0x3D,0x9F,0x3E,0x16,0x04 + } ; + + static _CODE BYTE bCSCMtx_RGB2YUV_ITU601_0_255[] = + { + 0x09,0x04,0x0E,0x02,0xC8,0x00, + 0x0E,0x3D,0x83,0x03,0x6E,0x3F, + 0xAC,0x3D,0xD0,0x3E,0x83,0x03 + } ; + + static _CODE BYTE bCSCMtx_RGB2YUV_ITU709_16_235[] = + { + 0xB8,0x05,0xB4,0x01,0x93,0x00, + 0x49,0x3C,0x16,0x04,0x9F,0x3F, + 0xD9,0x3C,0x10,0x3F,0x16,0x04 + } ; + + static _CODE BYTE bCSCMtx_RGB2YUV_ITU709_0_255[] = + { + 0xE5,0x04,0x78,0x01,0x81,0x00, + 0xCE,0x3C,0x83,0x03,0xAE,0x3F, + 0x49,0x3D,0x33,0x3F,0x83,0x03 + } ; +#endif +/* +#ifdef SUPPORT_INPUTYUV + + static _CODE BYTE bCSCMtx_YUV2RGB_ITU601_16_235[] = + { + 0x00,0x08,0x6A,0x3A,0x4F,0x3D, + 0x00,0x08,0xF7,0x0A,0x00,0x00, + 0x00,0x08,0x00,0x00,0xDB,0x0D + } ; + + static _CODE BYTE bCSCMtx_YUV2RGB_ITU601_0_255[] = + { + 0x4F,0x09,0x81,0x39,0xDF,0x3C, + 0x4F,0x09,0xC2,0x0C,0x00,0x00, + 0x4F,0x09,0x00,0x00,0x1E,0x10 + } ; + + static _CODE BYTE bCSCMtx_YUV2RGB_ITU709_16_235[] = + { + 0x00,0x08,0x53,0x3C,0x89,0x3E, + 0x00,0x08,0x51,0x0C,0x00,0x00, + 0x00,0x08,0x00,0x00,0x87,0x0E + } ; + + static _CODE BYTE bCSCMtx_YUV2RGB_ITU709_0_255[] = + { + 0x4F,0x09,0xBA,0x3B,0x4B,0x3E, + 0x4F,0x09,0x56,0x0E,0x00,0x00, + 0x4F,0x09,0x00,0x00,0xE7,0x10 + } ; +#endif*/ + +#ifdef SUPPORT_INPUTYUV + + BYTE bCSCMtx_YUV2RGB_ITU601_16_235[] = + { + 0x00,0x08,0x6A,0x3A,0x4F,0x3D, + 0x00,0x08,0xF7,0x0A,0x00,0x00, + 0x00,0x08,0x00,0x00,0xDB,0x0D + } ; + + BYTE bCSCMtx_YUV2RGB_ITU601_0_255[] = + { + 0x4F,0x09,0x81,0x39,0xDF,0x3C, + 0x4F,0x09,0xC2,0x0C,0x00,0x00, + 0x4F,0x09,0x00,0x00,0x1E,0x10 + } ; + + BYTE bCSCMtx_YUV2RGB_ITU709_16_235[] = + { + 0x00,0x08,0x53,0x3C,0x89,0x3E, + 0x00,0x08,0x51,0x0C,0x00,0x00, + 0x00,0x08,0x00,0x00,0x87,0x0E + } ; + + BYTE bCSCMtx_YUV2RGB_ITU709_0_255[] = + { + 0x4F,0x09,0xBA,0x3B,0x4B,0x3E, + 0x4F,0x09,0x56,0x0E,0x00,0x00, + 0x4F,0x09,0x00,0x00,0xE7,0x10 + } ; +#endif + + + +////////////////////////////////////////////////////////////////////// +// external Interface // +////////////////////////////////////////////////////////////////////// + +void +HDMITX_InitInstance(INSTANCE *pInstance) +{ + if(pInstance && 0 < HDMITX_INSTANCE_MAX) + { + Instance[0] = *pInstance ; + } +} + +static BYTE InitIT6613_HDCPROM() +{ + BYTE uc[5] ; + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(0xF8,0xC3) ; //password + HDMITX_WriteI2C_Byte(0xF8,0xA5) ; // password + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0x60) ; // Richard, ???? + I2C_Read_ByteN(0xE0,0x00,uc,5) ; // richard note. internal rom is used + + if(uc[0] == 1 && + uc[1] == 1 && + uc[2] == 1 && + uc[3] == 1 && + uc[4] == 1) + { + // with internal eMem + HDMITX_WriteI2C_Byte(REG_TX_ROM_HEADER,0xE0) ; + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0x48) ; + } + else + { + // with external ROM + HDMITX_WriteI2C_Byte(REG_TX_ROM_HEADER,0xA0) ; // ROMHeader + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0x00) ; // Richard, ???? + } + HDMITX_WriteI2C_Byte(0xF8,0xFF) ; // password + + // richard add + return ER_SUCCESS; +} + +void InitIT6613() +{ + // config interrupt + HDMITX_WriteI2C_Byte(REG_TX_INT_CTRL,Instance[0].bIntType) ; + Instance[0].bIntPOL = (Instance[0].bIntType&B_INTPOL_ACTH)?TRUE:FALSE ; + + // Reset + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_REF_RST|B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + DelayMS(1) ; + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + +#if 0 + // Enable clock ring (richard add according toe programming guide) + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL, 0x10); + + // Set default DVI mode (richard add according toe programming guide) +// HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE, 0x01); // set HDMI mode + HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE, 0x00); // set DVI mode +#endif + + // Avoid power loading in un play status. + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; + + // set interrupt mask,mask value 0 is interrupt available. +// richard HDMITX_WriteI2C_Byte(REG_TX_INT_MASK1,0xB2) ; // enable interrupt: HPD, DDCBusHangMask, + HDMITX_WriteI2C_Byte(REG_TX_INT_MASK1,0xB2) ; // enable interrupt: HPD, DDCBusHangMask, + HDMITX_WriteI2C_Byte(REG_TX_INT_MASK2,0xF8) ; // enable interrupt: AuthFailMask, AUthDoneMask, KSVListChkMask + HDMITX_WriteI2C_Byte(REG_TX_INT_MASK3,0x37) ; // enable interrupt: PktAudMask, PktDBDMask, PkMpgMask, AUdCTSMask, HDCPSynDetMask + + Switch_HDMITX_Bank(0) ; + DISABLE_NULL_PKT() ; + DISABLE_ACP_PKT() ; + DISABLE_ISRC1_PKT() ; + DISABLE_ISRC2_PKT() ; + DISABLE_AVI_INFOFRM_PKT() ; + DISABLE_AUD_INFOFRM_PKT() ; + DISABLE_SPD_INFOFRM_PKT() ; + DISABLE_MPG_INFOFRM_PKT(); + + + ////////////////////////////////////////////////////////////////// + // Setup Output Audio format. + ////////////////////////////////////////////////////////////////// + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,Instance[0].bOutputAudioMode) ; // regE1 bOutputAudioMode should be loaded from ROM image. + + ////////////////////////////////////////////////////////////////// + // Setup HDCP ROM + ////////////////////////////////////////////////////////////////// +#ifdef SUPPORT_HDCP + InitIT6613_HDCPROM() ; +#endif +// #ifdef EXTERN_HDCPROM +// #pragma message("EXTERN ROM CODED") ; +// HDMITX_WriteI2C_Byte(REG_TX_ROM_HEADER,0xA0) ; +// #endif + + +} + +////////////////////////////////////////////////////////////////////// +// export this for dynamic change input signal +////////////////////////////////////////////////////////////////////// +BOOL SetupVideoInputSignal(BYTE inputSignalType) +{ + Instance[0].bInputVideoSignalType = inputSignalType ; + // SetInputMode(inputColorMode,Instance[0].bInputVideoSignalType) ; + return TRUE ; +} + +BOOL EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) +{ + // bInputVideoMode,bOutputVideoMode,Instance[0].bInputVideoSignalType,bAudioInputType,should be configured by upper F/W or loaded from EEPROM. + // should be configured by initsys.c + WORD i ; + BYTE uc ; + // VIDEOPCLKLEVEL level ; + + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_VID_RST|B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + + Instance[0].bHDMIMode = (BYTE)bHDMI ; + + if(Instance[0].bHDMIMode) + { + SetAVMute(TRUE) ; + } + + SetInputMode(inputColorMode,Instance[0].bInputVideoSignalType) ; + + SetCSCScale(inputColorMode,outputColorMode) ; + + if(Instance[0].bHDMIMode) + { + HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE,B_TX_HDMI_MODE) ; + } + else + { + HDMITX_WriteI2C_Byte(REG_TX_HDMI_MODE,B_TX_DVI_MODE) ; + } + +#ifdef INVERT_VID_LATCHEDGE + uc = HDMITX_ReadI2C_Byte(REG_TX_CLK_CTRL1) ; + uc |= B_VDO_LATCH_EDGE ; + HDMITX_WriteI2C_Byte(REG_TX_CLK_CTRL1, uc) ; +#endif + + HDMITX_WriteI2C_Byte(REG_TX_SW_RST, B_AUD_RST|B_AREF_RST|B_HDCP_RST) ; + + // if (pVTiming->VideoPixelClock>80000000) + // { + // level = PCLK_HIGH ; + // } + // else if (pVTiming->VideoPixelClock>20000000) + // { + // level = PCLK_MEDIUM ; + // } + // else + // { + // level = PCLK_LOW ; + // } + + SetupAFE(level) ; // pass if High Freq request + + for(i = 0 ; i < 100 ; i++) + { + if(HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) & B_TXVIDSTABLE) + { + break ; + + } + DelayMS(1) ; + } + // Clive suggestion. + // clear int3 video stable interrupt. + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,0) ; + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,B_CLR_VIDSTABLE) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; + + FireAFE() ; + return TRUE ; +} + +BOOL EnableAudioOutput(ULONG VideoPixelClock,BYTE bAudioSampleFreq,BYTE ChannelNumber,BYTE bAudSWL,BYTE bSPDIF) +{ + BYTE bAudioChannelEnable ; + // richard unsigned long N ; + + Instance[0].TMDSClock = VideoPixelClock ; + Instance[0].bAudFs = bAudioSampleFreq ; + + ErrorF("EnableAudioOutput(%d,%ld,%x,%d,%d,%d);\n",0,VideoPixelClock,bAudioSampleFreq,ChannelNumber,bAudSWL,bSPDIF) ; + + switch(ChannelNumber) + { + case 7: + case 8: + bAudioChannelEnable = 0xF ; + break ; + case 6: + case 5: + bAudioChannelEnable = 0x7 ; + break ; + case 4: + case 3: + bAudioChannelEnable = 0x3 ; + break ; + case 2: + case 1: + default: + bAudioChannelEnable = 0x1 ; + break ; + } + + if(bSPDIF) bAudioChannelEnable |= B_AUD_SPDIF ; + + if( bSPDIF ) + { + Switch_HDMITX_Bank(1) ; + HDMITX_WriteI2C_Byte(REGPktAudCTS0,0x50) ; + HDMITX_WriteI2C_Byte(REGPktAudCTS1,0x73) ; + HDMITX_WriteI2C_Byte(REGPktAudCTS2,0x00) ; + + HDMITX_WriteI2C_Byte(REGPktAudN0,0) ; + HDMITX_WriteI2C_Byte(REGPktAudN1,0x18) ; + HDMITX_WriteI2C_Byte(REGPktAudN2,0) ; + Switch_HDMITX_Bank(0) ; + + HDMITX_WriteI2C_Byte(0xC5, 2) ; // D[1] = 0, HW auto count CTS + } + else + { + SetNCTS(VideoPixelClock,bAudioSampleFreq) ; + } + + /* + if(VideoPixelClock != 0) + { + SetNCTS(VideoPixelClock,bAudioSampleFreq) ; + } + else + { + switch(bAudioSampleFreq) + { + case AUDFS_32KHz: N = 4096; break; + case AUDFS_44p1KHz: N = 6272; break; + case AUDFS_48KHz: N = 6144; break; + case AUDFS_88p2KHz: N = 12544; break; + case AUDFS_96KHz: N = 12288; break; + case AUDFS_176p4KHz: N = 25088; break; + case AUDFS_192KHz: N = 24576; break; + default: N = 6144; + } + Switch_HDMITX_Bank(1) ; + HDMITX_WriteI2C_Byte(REGPktAudN0,(BYTE)((N)&0xFF)) ; + HDMITX_WriteI2C_Byte(REGPktAudN1,(BYTE)((N>>8)&0xFF)) ; + HDMITX_WriteI2C_Byte(REGPktAudN2,(BYTE)((N>>16)&0xF)) ; + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(REG_TX_PKT_SINGLE_CTRL,0) ; // D[1] = 0,HW auto count CTS + } + */ + + //HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_AUD_RST|B_AREF_RST)) ; + SetAudioFormat(ChannelNumber,bAudioChannelEnable,bAudioSampleFreq,bAudSWL,bSPDIF) ; + + #ifdef HDMITX_REG_DEBUG + DumpCatHDMITXReg() ; + #endif // HDMITX_REG_DEBUG + return TRUE ; +} + + +BOOL +GetEDIDData(int EDIDBlockID,BYTE *pEDIDData) +{ + if(!pEDIDData) + { + return FALSE ; + } + + if(ReadEDID(pEDIDData,EDIDBlockID/2,(EDIDBlockID%2)*128,128) == ER_FAIL) + { + return FALSE ; + } + + return TRUE ; +} + + +BOOL +EnableHDCP(BYTE bEnable) +{ + if(bEnable) + { + if(ER_FAIL == HDCP_Authenticate()) + { + + HDCP_ResetAuth() ; + return FALSE ; + } + + } + else + { + HDCP_ResetAuth() ; + } + return TRUE ; +} + + +BOOL +CheckHDMITX(BYTE *pHPD,BYTE *pHPDChange) +{ + BYTE intdata1,intdata2,intdata3,sysstat; + BYTE intclr3 = 0 ; + BOOL PrevHPD = Instance[0].bHPD ; + BOOL HPD ; + + sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) ; // read system status register + + // OS_PRINTF("sysstat(REG[0x0E])=%02Xh\r\n", sysstat); + + HPD = ((sysstat & (B_HPDETECT|B_RXSENDETECT)) == (B_HPDETECT|B_RXSENDETECT))?TRUE:FALSE ; + + // 2007/06/20 added by jj_tseng@chipadvanced.com + if(pHPDChange) + { + *pHPDChange = FALSE ; + + } + //~jj_tseng@chipadvanced.com 2007/06/20 + + if(!HPD) + { + Instance[0].bAuthenticated = FALSE ; + } + + if(sysstat & B_INT_ACTIVE) // interrupt is activce + { + + intdata1 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) ; // reg 0x06 + //ErrorF("INT_Handler: reg%02x = %02x\n",REG_TX_INT_STAT1,intdata1) ; + + if(intdata1 & B_INT_DDCFIFO_ERR) + { + //ErrorF("DDC FIFO Error.\n") ; + ClearDDCFIFO() ; + } + + + if(intdata1 & B_INT_DDC_BUS_HANG) + { + ErrorF("DDC BUS HANG.\n") ; + AbortDDC() ; + + if(Instance[0].bAuthenticated) + { + ErrorF("when DDC hang,and aborted DDC,the HDCP authentication need to restart.\n") ; + HDCP_ResumeAuthentication() ; + } + } + + + if(intdata1 & (B_INT_HPD_PLUG|B_INT_RX_SENSE)) + { + + if(pHPDChange) *pHPDChange = TRUE ; + + if(!HPD) + { + // reset + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_AREF_RST|B_VID_RST|B_AUD_RST|B_HDCP_RST) ; + DelayMS(1) ; + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; + //ErrorF("Unplug,%x %x\n",HDMITX_ReadI2C_Byte(REG_TX_SW_RST),HDMITX_ReadI2C_Byte(REG_TX_AFE_DRV_CTRL)) ; + // VState = TXVSTATE_Unplug ; + } + } + + + intdata2 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2) ; // reg 0x07 + //ErrorF("INT_Handler: reg%02x = %02x\n",REG_TX_INT_STAT2,intdata2) ; + + + + #ifdef SUPPORT_HDCP + if(intdata2 & B_INT_AUTH_DONE) + { + ErrorF("interrupt Authenticate Done.\n") ; + HDMITX_OrREG_Byte(REG_TX_INT_MASK2,B_T_AUTH_DONE_MASK) ; + Instance[0].bAuthenticated = TRUE ; + SetAVMute(FALSE) ; + } + + if(intdata2 & B_INT_AUTH_FAIL) + { + ErrorF("interrupt Authenticate Fail.\n") ; + AbortDDC(); // @emily add + HDCP_ResumeAuthentication() ; + } + #endif // SUPPORT_HDCP + + intdata3 = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT3) ; // reg 0x08 + if(intdata3 & B_INT_VIDSTABLE) + { + sysstat = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) ; + if(sysstat & B_TXVIDSTABLE) + { + FireAFE() ; + } + } + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,0xFF) ; + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0xFF) ; + intclr3 = (HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS))|B_CLR_AUD_CTS | B_INTACTDONE ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3) ; // clear interrupt. + intclr3 &= ~(B_INTACTDONE) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,intclr3) ; // INTACTDONE reset to zero. + } + else + { + if(pHPDChange) + { + *pHPDChange = (HPD != PrevHPD)?TRUE:FALSE ; + + if(*pHPDChange &&(!HPD)) + { + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; + } + } + } + + SetupAudioChannel() ; // 2007/12/12 added by jj_tseng + + if(pHPD) + { + *pHPD = HPD ? TRUE:FALSE ; + } + + Instance[0].bHPD = (BYTE)HPD ; + return HPD ; +} + +void +DisableIT6613() +{ + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,B_AREF_RST|B_VID_RST|B_AUD_RST|B_HDCP_RST) ; + DelayMS(1) ; + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; +} + +void +DisableVideoOutput() +{ + BYTE uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_VID_RST ; + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc) ; + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST|B_AFE_DRV_PWD) ; +} + + +void +DisableAudioOutput() +{ + BYTE uc = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) | B_AUD_RST ; + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,uc) ; +} + + + +BOOL +EnableAVIInfoFrame(BYTE bEnable,BYTE *pAVIInfoFrame) +{ + if(!bEnable) + { + DISABLE_AVI_INFOFRM_PKT() ; + return TRUE ; + } + + if(SetAVIInfoFrame((AVI_InfoFrame *)pAVIInfoFrame) == ER_SUCCESS) + { + return TRUE ; + } + + return FALSE ; +} + +BOOL +EnableAudioInfoFrame(BYTE bEnable,BYTE *pAudioInfoFrame) +{ + if(!bEnable) + { + // richard modify, DISABLE_AVI_INFOFRM_PKT() ; + DISABLE_AUD_INFOFRM_PKT(); + return TRUE ; + } + + + if(SetAudioInfoFrame((Audio_InfoFrame *)pAudioInfoFrame) == ER_SUCCESS) + { + return TRUE ; + } + + return FALSE ; +} + +void +SetAVMute(BYTE bEnable) +{ + BYTE uc ; + + Switch_HDMITX_Bank(0) ; + uc = HDMITX_ReadI2C_Byte(REG_TX_GCP) ; + uc &= ~B_TX_SETAVMUTE ; + uc |= bEnable?B_TX_SETAVMUTE:0 ; + HDMITX_WriteI2C_Byte(REG_TX_GCP,uc) ; + HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT) ; +} + +void +SetOutputColorDepthPhase(BYTE ColorDepth,BYTE bPhase) +{ + BYTE uc ; + BYTE bColorDepth ; + + if(ColorDepth == 30) + { + bColorDepth = B_CD_30 ; + } + else if (ColorDepth == 36) + { + bColorDepth = B_CD_36 ; + } + else if (ColorDepth == 24) + { + bColorDepth = B_CD_24 ; + } + else + { + bColorDepth = 0 ; // not indicated + } + + Switch_HDMITX_Bank(0) ; + uc = HDMITX_ReadI2C_Byte(REG_TX_GCP) ; + uc &= ~B_COLOR_DEPTH_MASK ; + uc |= bColorDepth&B_COLOR_DEPTH_MASK; + HDMITX_WriteI2C_Byte(REG_TX_GCP,uc) ; +} + +void +Get6613Reg(BYTE *pReg) +{ + int i ; + BYTE reg ; + Switch_HDMITX_Bank(0) ; + for(i = 0 ; i < 0x100 ; i++) + { + reg = i & 0xFF ; + pReg[i] = HDMITX_ReadI2C_Byte(reg) ; + } + Switch_HDMITX_Bank(1) ; + for(reg = 0x30 ; reg < 0xB0 ; i++,reg++) + { + pReg[i] = HDMITX_ReadI2C_Byte(reg) ; + } + Switch_HDMITX_Bank(0) ; + +} +////////////////////////////////////////////////////////////////////// +// SubProcedure process // +////////////////////////////////////////////////////////////////////// +#ifdef SUPPORT_DEGEN + +typedef struct { + MODE_ID id ; + BYTE Reg90; + BYTE Reg92; + BYTE Reg93; + BYTE Reg94; + BYTE Reg9A; + BYTE Reg9B; + BYTE Reg9C; + BYTE Reg9D; + BYTE Reg9E; + BYTE Reg9F; +} DEGEN_Setting ; + + +static _CODE DEGEN_Setting DeGen_Table[] = { + {CEA_640x480p60 ,0x01,0x8E,0x0E,0x30,0x22,0x02,0x20,0xFF,0xFF,0xFF}, + // HDES = 142, HDEE = 782, VDES = 34, VDEE = 514 + {CEA_720x480p60 ,0x01,0x78,0x48,0x30,0x23,0x03,0x20,0xFF,0xFF,0xFF}, + // HDES = 120, HDEE = 840, VDES = 35, VDEE = 515 + {CEA_1280x720p60 ,0x07,0x02,0x02,0x61,0x18,0xE8,0x20,0xFF,0xFF,0xFF}, + // HDES = 258, HDEE = 1538, VDES = 24, VDEE = 744 +// {CEA_1920x1080i60 ,0x07,0xBE,0x3E,0x80,0x13,0x2F,0x20,0x45,0x61,0x42}, +// // HDES = 190, HDEE = 2110, VDES = 19, VDEE = 559, VDS2 = 581, VDE2 = 1121 + {CEA_1920x1080i60 ,0x07,0xBE,0x3E,0x80,0x13,0x2F,0x20,0x46,0x62,0x42}, + // HDES = 190, HDEE = 2110, VDES = 19, VDEE = 559, VDS2 = 582, VDE2 = 1122 + + {CEA_720x480i60 ,0x01,0x75,0x45,0x30,0x11,0x01,0x10,0x17,0x07,0x21}, + // HDES = 117, HDEE = 837, VDES = 17, VDEE = 257, VDS2 = 279, VDE2 = 519 + {CEA_720x240p60 ,0x01,0x75,0x45,0x30,0x11,0x01,0x10,0xFF,0xFF,0xFF}, + // HDES = 117, HDEE = 837, VDES = 17, VDEE = 257 + {CEA_1440x480i60 ,0x01,0xEC,0x8C,0x60,0x11,0x01,0x10,0x17,0x07,0x21}, + // HDES = 236, HDEE = 1676, VDES = 17, VDEE = 257, VDS2 = 279, VDE2 = 519 + {CEA_1440x240p60 ,0x01,0xEC,0x8C,0x60,0x11,0x01,0x10,0xFF,0xFF,0xFF}, + // HDES = 236, HDEE = 1676, VDES = 17, VDEE = 257 + {CEA_2880x480i60 ,0x01,0x16,0x56,0xD2,0x11,0x01,0x10,0x17,0x07,0x21}, + // HDES = 534, HDEE = 3414, VDES = 17, VDEE = 257, VDS2 = 279, VDE2 = 519 + {CEA_2880x240p60 ,0x01,0x16,0x56,0xD2,0x11,0x01,0x10,0xFF,0xFF,0xFF}, + // HDES = 534, HDEE = 3414, VDES = 17, VDEE = 257 + {CEA_1440x480p60 ,0x01,0xF2,0x92,0x60,0x23,0x03,0x20,0xFF,0xFF,0xFF}, + // HDES = 242, HDEE = 1682, VDES = 35, VDEE = 515 + {CEA_1920x1080p60 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, + // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 + {CEA_720x576p50 ,0x01,0x82,0x52,0x30,0x2b,0x6b,0x20,0xFF,0xFF,0xFF}, + // HDES = 130, HDEE = 850, VDES = 43, VDEE = 619 + {CEA_1280x720p50 ,0x07,0x02,0x02,0x61,0x18,0xE8,0x20,0xFF,0xFF,0xFF}, + // HDES = 258, HDEE = 1538, VDES = 24, VDEE = 744 + {CEA_1920x1080i50 ,0x07,0xBE,0x3E,0x80,0x13,0x2F,0x20,0x46,0x62,0x42}, + // HDES = 190, HDEE = 2110, VDES = 19, VDEE = 559, VDS2 = 582, VDE2 = 1122 + {CEA_720x576i50 ,0x01,0x82,0x52,0x30,0x15,0x35,0x10,0x4D,0x6D,0x21}, + // HDES = 130, HDEE = 850, VDES = 21, VDEE = 309, VDS2 = 333, VDE2 = 621 + {CEA_1440x576i50 ,0x01,0x06,0xA6,0x61,0x15,0x35,0x10,0x4D,0x6D,0x21}, + // HDES = 262, HDEE = 1702, VDES = 21, VDEE = 309, VDS2 = 333, VDE2 = 621 + {CEA_720x288p50 ,0x01,0x82,0x52,0x30,0x15,0x35,0x10,0xFF,0xFF,0xFF}, + // HDES = 130, HDEE = 850, VDES = 21, VDEE = 309 + {CEA_1440x288p50 ,0x01,0x06,0xA6,0x61,0x15,0x35,0x10,0xFF,0xFF,0xFF}, + // HDES = 262, HDEE = 1702, VDES = 21, VDEE = 309 + {CEA_2880x576i50 ,0x01,0x0E,0x4E,0xD2,0x15,0x35,0x10,0x4D,0x6D,0x21}, + // HDES = 526, HDEE = 3406, VDES = 21, VDEE = 309, VDS2 = 333, VDE2 = 621 + {CEA_2880x288p50 ,0x01,0x0E,0x4E,0xD2,0x15,0x35,0x10,0xFF,0xFF,0xFF}, + // HDES = 526, HDEE = 3406, VDES = 21, VDEE = 309 + {CEA_1440x576p50 ,0x05,0x06,0xA6,0x61,0x2B,0x6B,0x20,0xFF,0xFF,0xFF}, + // HDES = 262, HDEE = 1702, VDES = 43, VDEE = 619 + {CEA_1920x1080p50 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, + // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 + {CEA_1920x1080p24 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, + // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 + {CEA_1920x1080p25 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, + // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 + {CEA_1920x1080p30 ,0x07,0xBE,0x3E,0x80,0x28,0x60,0x40,0xFF,0xFF,0xFF}, + // HDES = 190, HDEE = 2110, VDES = 40, VDEE = 1120 + {VESA_640x350p85 ,0x03,0x9E,0x1E,0x30,0x3E,0x9C,0x10,0xFF,0xFF,0xFF}, + // HDES = 158, HDEE = 798, VDES = 62, VDEE = 412 + {VESA_640x400p85 ,0x05,0x9E,0x1E,0x30,0x2B,0xBB,0x10,0xFF,0xFF,0xFF}, + // HDES = 158, HDEE = 798, VDES = 43, VDEE = 443 + {VESA_720x400p85 ,0x05,0xB2,0x82,0x30,0x2C,0xBC,0x10,0xFF,0xFF,0xFF}, + // HDES = 178, HDEE = 898, VDES = 44, VDEE = 444 + {VESA_640x480p60 ,0x01,0x8E,0x0E,0x30,0x22,0x02,0x20,0xFF,0xFF,0xFF}, + // HDES = 142, HDEE = 782, VDES = 34, VDEE = 514 + {VESA_640x480p72 ,0x01,0xA6,0x26,0x30,0x1E,0xFE,0x10,0xFF,0xFF,0xFF}, + // HDES = 166, HDEE = 806, VDES = 30, VDEE = 510 + {VESA_640x480p75 ,0x01,0xB6,0x36,0x30,0x12,0xF2,0x10,0xFF,0xFF,0xFF}, + // HDES = 182, HDEE = 822, VDES = 18, VDEE = 498 + {VESA_640x480p85 ,0x01,0x86,0x06,0x30,0x1B,0xFB,0x10,0xFF,0xFF,0xFF}, + // HDES = 134, HDEE = 774, VDES = 27, VDEE = 507 + {VESA_800x600p56 ,0x07,0xC6,0xE6,0x30,0x17,0x6F,0x20,0xFF,0xFF,0xFF}, + // HDES = 198, HDEE = 998, VDES = 23, VDEE = 623 + {VESA_800x600p60 ,0x07,0xD6,0xF6,0x30,0x1A,0x72,0x20,0xFF,0xFF,0xFF}, + // HDES = 214, HDEE = 1014, VDES = 26, VDEE = 626 + {VESA_800x600p72 ,0x07,0xB6,0xD6,0x30,0x1C,0x74,0x20,0xFF,0xFF,0xFF}, + // HDES = 182, HDEE = 982, VDES = 28, VDEE = 628 + {VESA_800x600p75 ,0x07,0xEE,0x0E,0x40,0x17,0x6F,0x20,0xFF,0xFF,0xFF}, + // HDES = 238, HDEE = 1038, VDES = 23, VDEE = 623 + {VESA_800X600p85 ,0x07,0xD6,0xF6,0x30,0x1D,0x75,0x20,0xFF,0xFF,0xFF}, + // HDES = 214, HDEE = 1014, VDES = 29, VDEE = 629 + {VESA_840X480p60 ,0x07,0xDE,0x2E,0x40,0x1E,0xFE,0x10,0xFF,0xFF,0xFF}, + // HDES = 222, HDEE = 1070, VDES = 30, VDEE = 510 + {VESA_1024x768p60 ,0x01,0x26,0x26,0x51,0x22,0x22,0x30,0xFF,0xFF,0xFF}, + // HDES = 294, HDEE = 1318, VDES = 34, VDEE = 802 + {VESA_1024x768p70 ,0x01,0x16,0x16,0x51,0x22,0x22,0x30,0xFF,0xFF,0xFF}, + // HDES = 278, HDEE = 1302, VDES = 34, VDEE = 802 + {VESA_1024x768p75 ,0x07,0x0E,0x0E,0x51,0x1E,0x1E,0x30,0xFF,0xFF,0xFF}, + // HDES = 270, HDEE = 1294, VDES = 30, VDEE = 798 + {VESA_1024x768p85 ,0x07,0x2E,0x2E,0x51,0x26,0x26,0x30,0xFF,0xFF,0xFF}, + // HDES = 302, HDEE = 1326, VDES = 38, VDEE = 806 + {VESA_1152x864p75 ,0x07,0x7E,0xFE,0x51,0x22,0x82,0x30,0xFF,0xFF,0xFF}, + // HDES = 382, HDEE = 1534, VDES = 34, VDEE = 898 + {VESA_1280x768p60R ,0x03,0x6E,0x6E,0x50,0x12,0x12,0x30,0xFF,0xFF,0xFF}, + // HDES = 110, HDEE = 1390, VDES = 18, VDEE = 786 + {VESA_1280x768p60 ,0x05,0x3E,0x3E,0x61,0x1A,0x1A,0x30,0xFF,0xFF,0xFF}, + // HDES = 318, HDEE = 1598, VDES = 26, VDEE = 794 + {VESA_1280x768p75 ,0x05,0x4E,0x4E,0x61,0x21,0x21,0x30,0xFF,0xFF,0xFF}, + // HDES = 334, HDEE = 1614, VDES = 33, VDEE = 801 + {VESA_1280x768p85 ,0x05,0x5E,0x5E,0x61,0x25,0x25,0x30,0xFF,0xFF,0xFF}, + // HDES = 350, HDEE = 1630, VDES = 37, VDEE = 805 + {VESA_1280x960p60 ,0x07,0xA6,0xA6,0x61,0x26,0xE6,0x30,0xFF,0xFF,0xFF}, + // HDES = 422, HDEE = 1702, VDES = 38, VDEE = 998 + {VESA_1280x960p85 ,0x07,0x7E,0x7E,0x61,0x31,0xF1,0x30,0xFF,0xFF,0xFF}, + // HDES = 382, HDEE = 1662, VDES = 49, VDEE = 1009 + {VESA_1280x1024p60 ,0x07,0x66,0x66,0x61,0x28,0x28,0x40,0xFF,0xFF,0xFF}, + // HDES = 358, HDEE = 1638, VDES = 40, VDEE = 1064 + {VESA_1280x1024p75 ,0x07,0x86,0x86,0x61,0x28,0x28,0x40,0xFF,0xFF,0xFF}, + // HDES = 390, HDEE = 1670, VDES = 40, VDEE = 1064 + {VESA_1280X1024p85 ,0x07,0x7E,0x7E,0x61,0x2E,0x2E,0x40,0xFF,0xFF,0xFF}, + // HDES = 382, HDEE = 1662, VDES = 46, VDEE = 1070 + {VESA_1360X768p60 ,0x07,0x6E,0xBE,0x61,0x17,0x17,0x30,0xFF,0xFF,0xFF}, + // HDES = 366, HDEE = 1726, VDES = 23, VDEE = 791 + {VESA_1400x768p60R ,0x03,0x6E,0xE6,0x50,0x1A,0x34,0x40,0xFF,0xFF,0xFF}, + // HDES = 110, HDEE = 1510, VDES = 26, VDEE = 1076 + {VESA_1400x768p60 ,0x05,0x76,0xEE,0x61,0x23,0x3D,0x40,0xFF,0xFF,0xFF}, + // HDES = 374, HDEE = 1774, VDES = 35, VDEE = 1085 + {VESA_1400x1050p75 ,0x05,0x86,0xFE,0x61,0x2D,0x47,0x40,0xFF,0xFF,0xFF}, + // HDES = 390, HDEE = 1790, VDES = 45, VDEE = 1095 + {VESA_1400x1050p85 ,0x05,0x96,0x0E,0x71,0x33,0x4D,0x40,0xFF,0xFF,0xFF}, + // HDES = 406, HDEE = 1806, VDES = 51, VDEE = 1101 + {VESA_1440x900p60R ,0x03,0x6E,0x0E,0x60,0x16,0x9A,0x30,0xFF,0xFF,0xFF}, + // HDES = 110, HDEE = 1550, VDES = 22, VDEE = 922 + {VESA_1440x900p60 ,0x05,0x7E,0x1E,0x71,0x1E,0xA2,0x30,0xFF,0xFF,0xFF}, + // HDES = 382, HDEE = 1822, VDES = 30, VDEE = 930 + {VESA_1440x900p75 ,0x05,0x8E,0x2E,0x71,0x26,0xAA,0x30,0xFF,0xFF,0xFF}, + // HDES = 398, HDEE = 1838, VDES = 38, VDEE = 938 + {VESA_1440x900p85 ,0x05,0x96,0x36,0x71,0x2C,0xB0,0x30,0xFF,0xFF,0xFF}, + // HDES = 406, HDEE = 1846, VDES = 44, VDEE = 944 + {VESA_1600x1200p60 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, + // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 + {VESA_1600x1200p65 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, + // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 + {VESA_1600x1200p70 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, + // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 + {VESA_1600x1200p75 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, + // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 + {VESA_1600x1200p85 ,0x07,0xEE,0x2E,0x81,0x30,0xE0,0x40,0xFF,0xFF,0xFF}, + // HDES = 494, HDEE = 2094, VDES = 48, VDEE = 1248 + {VESA_1680x1050p60R ,0x03,0x6E,0xFE,0x60,0x1A,0x34,0x40,0xFF,0xFF,0xFF}, + // HDES = 110, HDEE = 1790, VDES = 26, VDEE = 1076 + {VESA_1680x1050p60 ,0x05,0xC6,0x56,0x81,0x23,0x3D,0x40,0xFF,0xFF,0xFF}, + // HDES = 454, HDEE = 2134, VDES = 35, VDEE = 1085 + {VESA_1680x1050p75 ,0x05,0xD6,0x66,0x81,0x2D,0x47,0x40,0xFF,0xFF,0xFF}, + // HDES = 470, HDEE = 2150, VDES = 45, VDEE = 1095 + {VESA_1680x1050p85 ,0x05,0xDE,0x6E,0x81,0x33,0x4D,0x40,0xFF,0xFF,0xFF}, + // HDES = 478, HDEE = 2158, VDES = 51, VDEE = 1101 + {VESA_1792x1344p60 ,0x05,0x0E,0x0E,0x92,0x30,0x70,0x50,0xFF,0xFF,0xFF}, + // HDES = 526, HDEE = 2318, VDES = 48, VDEE = 1392 + {VESA_1792x1344p75 ,0x05,0x36,0x36,0x92,0x47,0x87,0x50,0xFF,0xFF,0xFF}, + // HDES = 566, HDEE = 2358, VDES = 71, VDEE = 1415 + {VESA_1856x1392p60 ,0x05,0x3E,0x7E,0x92,0x2D,0x9D,0x50,0xFF,0xFF,0xFF}, + // HDES = 574, HDEE = 2430, VDES = 45, VDEE = 1437 + {VESA_1856x1392p75 ,0x05,0x3E,0x7E,0x92,0x6A,0xDA,0x50,0xFF,0xFF,0xFF}, + // HDES = 574, HDEE = 2430, VDES = 106, VDEE = 1498 + {VESA_1920x1200p60R ,0x03,0x6E,0xEE,0x70,0x1F,0xCF,0x40,0xFF,0xFF,0xFF}, + // HDES = 110, HDEE = 2030, VDES = 31, VDEE = 1231 + {VESA_1920x1200p60 ,0x05,0x16,0x96,0x92,0x29,0xD9,0x40,0xFF,0xFF,0xFF}, + // HDES = 534, HDEE = 2454, VDES = 41, VDEE = 1241 + {VESA_1920x1200p75 ,0x05,0x26,0xA6,0x92,0x33,0xE3,0x40,0xFF,0xFF,0xFF}, + // HDES = 550, HDEE = 2470, VDES = 51, VDEE = 1251 + {VESA_1920x1200p85 ,0x05,0x2E,0xAE,0x92,0x3A,0xEA,0x40,0xFF,0xFF,0xFF}, + // HDES = 558, HDEE = 2478, VDES = 58, VDEE = 1258 + {VESA_1920x1440p60 ,0x05,0x26,0xA6,0x92,0x3A,0xDA,0x50,0xFF,0xFF,0xFF}, + // HDES = 550, HDEE = 2470, VDES = 58, VDEE = 1498 + {VESA_1920x1440p75 ,0x05,0x3E,0xBE,0x92,0x3A,0xDA,0x50,0xFF,0xFF,0xFF}, + // HDES = 574, HDEE = 2494, VDES = 58, VDEE = 1498 + {UNKNOWN_MODE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} +} ; + +BOOL ProgramDEGenModeByID(MODE_ID id,BYTE bInputSignalType) +{ + int i ; + if( (bInputSignalType & (T_MODE_DEGEN|T_MODE_SYNCGEN|T_MODE_SYNCEMB) )==(T_MODE_DEGEN)) + { + for( i = 0 ; DeGen_Table[i].id != UNKNOWN_MODE ; i++ ) + { + if( id == DeGen_Table[i].id ) break ; + } + if( DeGen_Table[i].id == UNKNOWN_MODE ) + { + return FALSE ; + } + + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(0x90,DeGen_Table[i].Reg90) ; + HDMITX_WriteI2C_Byte(0x92,DeGen_Table[i].Reg92) ; + HDMITX_WriteI2C_Byte(0x93,DeGen_Table[i].Reg93) ; + HDMITX_WriteI2C_Byte(0x94,DeGen_Table[i].Reg94) ; + HDMITX_WriteI2C_Byte(0x9A,DeGen_Table[i].Reg9A) ; + HDMITX_WriteI2C_Byte(0x9B,DeGen_Table[i].Reg9B) ; + HDMITX_WriteI2C_Byte(0x9C,DeGen_Table[i].Reg9C) ; + HDMITX_WriteI2C_Byte(0x9D,DeGen_Table[i].Reg9D) ; + HDMITX_WriteI2C_Byte(0x9E,DeGen_Table[i].Reg9E) ; + HDMITX_WriteI2C_Byte(0x9F,DeGen_Table[i].Reg9F) ; + return TRUE ; + + } + return FALSE ; +} + +#endif + +#ifdef SUPPORT_SYNCEMBEDDED +/* ****************************************************** */ +// sync embedded table setting,defined as comment. +/* ****************************************************** */ +struct SyncEmbeddedSetting { + BYTE fmt ; + BYTE RegHVPol ; // Reg90 + BYTE RegHfPixel ; // Reg91 + BYTE RegHSSL ; // Reg95 + BYTE RegHSEL ; // Reg96 + BYTE RegHSH ; // Reg97 + BYTE RegVSS1 ; // RegA0 + BYTE RegVSE1 ; // RegA1 + BYTE RegVSS2 ; // RegA2 + BYTE RegVSE2 ; // RegA3 + + ULONG PCLK ; + BYTE VFreq ; +} ; + +static _CODE struct SyncEmbeddedSetting SyncEmbTable[] = { + // {FMT,0x90,0x91, + // 0x95,0x96,0x97,0xA0,0xA1,0xA2,0xA3,PCLK,VFREQ}, + { 1,0xF0,0x31,0x0E,0x6E,0x00,0x0A,0xC0,0xFF,0xFF,25175000,60}, + { 2,0xF0,0x31,0x0E,0x4c,0x00,0x09,0xF0,0xFF,0xFF,27000000,60}, + { 3,0xF0,0x31,0x0E,0x4c,0x00,0x09,0xF0,0xFF,0xFF,27000000,60}, + { 4,0x76,0x33,0x6c,0x94,0x00,0x05,0xA0,0xFF,0xFF,74175000,60}, + { 5,0x26,0x4A,0x56,0x82,0x00,0x02,0x70,0x34,0x92,74175000,60}, + { 6,0xE0,0x1B,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,27000000,60}, + { 7,0xE0,0x1B,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,27000000,60}, + { 8,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,27000000,60}, + { 9,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,27000000,60}, + { 10,0xe0,0x1b,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,54000000,60}, + { 11,0xe0,0x1b,0x11,0x4F,0x00,0x04,0x70,0x0A,0xD1,54000000,60}, + { 12,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,54000000,60}, + { 13,0x00,0xff,0x11,0x4F,0x00,0x04,0x70,0xFF,0xFF,54000000,60}, + { 14,0x00,0xff,0x1e,0x9A,0x00,0x09,0xF0,0xFF,0xFF,54000000,60}, + { 15,0x00,0xff,0x1e,0x9A,0x00,0x09,0xF0,0xFF,0xFF,54000000,60}, + { 16,0x06,0xff,0x56,0x82,0x00,0x04,0x90,0xFF,0xFF,148350000,60}, + { 17,0x00,0xff,0x0a,0x4A,0x00,0x05,0xA0,0xFF,0xFF,27000000,50}, + { 18,0x00,0xff,0x0a,0x4A,0x00,0x05,0xA0,0xFF,0xFF,27000000,50}, + { 19,0x06,0xff,0xB6,0xDE,0x11,0x05,0xA0,0xFF,0xFF,74250000,50}, + { 20,0x66,0x73,0x0e,0x3A,0x22,0x02,0x70,0x34,0x92,74250000,50}, + { 21,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,27000000,50}, + { 22,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,27000000,50}, + { 23,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,27000000,50}, + { 24,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,27000000,50}, + { 25,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,54000000,50}, + { 26,0xA0,0x1B,0x0a,0x49,0x00,0x02,0x50,0x3A,0xD1,54000000,50}, + { 27,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,54000000,50}, + { 28,0x00,0xff,0x0a,0x49,0x00,0x02,0x50,0xFF,0xFF,54000000,50}, + { 29,0x04,0xff,0x16,0x96,0x00,0x05,0xA0,0xFF,0xFF,54000000,50}, + { 30,0x04,0xff,0x16,0x96,0x00,0x05,0xA0,0xFF,0xFF,54000000,50}, + { 31,0x06,0xff,0x0e,0x3a,0x22,0x04,0x90,0xFF,0xFF,148500000,50}, + {0xFF,0xFF,0xff,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0} +} ; + +BOOL +ProgramSyncEmbeddedVideoMode(BYTE VIC,BYTE bInputSignalType) +{ + int i ; + // if Embedded Video,need to generate timing with pattern register + + ErrorF("ProgramSyncEmbeddedVideoMode(%d,%x)\n",VIC,bInputSignalType) ; + + if( bInputSignalType & T_MODE_SYNCEMB ) + { + for(i = 0 ; SyncEmbTable[i].fmt != 0xFF ; i++) + { + if(VIC == SyncEmbTable[i].fmt) + { + break ; + } + } + + if(SyncEmbTable[i].fmt == 0xFF) + { + return FALSE ; + } + + HDMITX_WriteI2C_Byte(REG_TX_HVPol,SyncEmbTable[i].RegHVPol) ; // Reg90 + HDMITX_WriteI2C_Byte(REG_TX_HfPixel,SyncEmbTable[i].RegHfPixel) ; // Reg91 + + HDMITX_WriteI2C_Byte(REG_TX_HSSL,SyncEmbTable[i].RegHSSL) ; // Reg95 + HDMITX_WriteI2C_Byte(REG_TX_HSEL,SyncEmbTable[i].RegHSEL) ; // Reg96 + HDMITX_WriteI2C_Byte(REG_TX_HSH,SyncEmbTable[i].RegHSH) ; // Reg97 + HDMITX_WriteI2C_Byte(REG_TX_VSS1,SyncEmbTable[i].RegVSS1) ; // RegA0 + HDMITX_WriteI2C_Byte(REG_TX_VSE1,SyncEmbTable[i].RegVSE1) ; // RegA1 + + HDMITX_WriteI2C_Byte(REG_TX_VSS2,SyncEmbTable[i].RegVSS2) ; // RegA2 + HDMITX_WriteI2C_Byte(REG_TX_VSE2,SyncEmbTable[i].RegVSE2) ; // RegA3 + } + + return TRUE ; +} +#endif // SUPPORT_SYNCEMBEDDED + +//~jj_tseng@chipadvanced.com 2007/01/02 + + +////////////////////////////////////////////////////////////////////// +// Function: SetInputMode +// Parameter: InputMode,bInputSignalType +// InputMode - use [1:0] to identify the color space for reg70[7:6], +// definition: +// #define F_MODE_RGB444 0 +// #define F_MODE_YUV422 1 +// #define F_MODE_YUV444 2 +// #define F_MODE_CLRMOD_MASK 3 +// bInputSignalType - defined the CCIR656 D[0],SYNC Embedded D[1],and +// DDR input in D[2]. +// Return: N/A +// Remark: program Reg70 with the input value. +// Side-Effect: Reg70. +////////////////////////////////////////////////////////////////////// + +static void +SetInputMode(BYTE InputMode,BYTE bInputSignalType) +{ + BYTE ucData ; + + ErrorF("SetInputMode(%02X,%02X)\n",InputMode,bInputSignalType) ; + + ucData = HDMITX_ReadI2C_Byte(REG_TX_INPUT_MODE) ; + + ucData &= ~(M_INCOLMOD|B_2X656CLK|B_SYNCEMB|B_INDDR|B_PCLKDIV2) ; + + switch(InputMode & F_MODE_CLRMOD_MASK) + { + case F_MODE_YUV422: + ucData |= B_IN_YUV422 ; + break ; + case F_MODE_YUV444: + ucData |= B_IN_YUV444 ; + break ; + case F_MODE_RGB444: + default: + ucData |= B_IN_RGB ; + break ; + } + + if(bInputSignalType & T_MODE_PCLKDIV2) + { + ucData |= B_PCLKDIV2 ; ErrorF("PCLK Divided by 2 mode\n") ; + } + if(bInputSignalType & T_MODE_CCIR656) + { + ucData |= B_2X656CLK ; ErrorF("CCIR656 mode\n") ; + } + + if(bInputSignalType & T_MODE_SYNCEMB) + { + ucData |= B_SYNCEMB ; ErrorF("Sync Embedded mode\n") ; + } + + if(bInputSignalType & T_MODE_INDDR) + { + ucData |= B_INDDR ; ErrorF("Input DDR mode\n") ; + } + + HDMITX_WriteI2C_Byte(REG_TX_INPUT_MODE,ucData) ; +} + +////////////////////////////////////////////////////////////////////// +// Function: SetCSCScale +// Parameter: bInputMode - +// D[1:0] - Color Mode +// D[4] - Colorimetry 0: ITU_BT601 1: ITU_BT709 +// D[5] - Quantization 0: 0_255 1: 16_235 +// D[6] - Up/Dn Filter 'Required' +// 0: no up/down filter +// 1: enable up/down filter when csc need. +// D[7] - Dither Filter 'Required' +// 0: no dither enabled. +// 1: enable dither and dither free go "when required". +// bOutputMode - +// D[1:0] - Color mode. +// Return: N/A +// Remark: reg72~reg8D will be programmed depended the input with table. +// Side-Effect: +////////////////////////////////////////////////////////////////////// + +static void +SetCSCScale(BYTE bInputMode,BYTE bOutputMode) +{ + BYTE ucData,csc ; + BYTE filter = 0 ; // filter is for Video CTRL DN_FREE_GO,EN_DITHER,and ENUDFILT + + + // (1) YUV422 in,RGB/YUV444 output (Output is 8-bit,input is 12-bit) + // (2) YUV444/422 in,RGB output (CSC enable,and output is not YUV422) + // (3) RGB in,YUV444 output (CSC enable,and output is not YUV422) + // + // YUV444/RGB24 <-> YUV422 need set up/down filter. + + switch(bInputMode&F_MODE_CLRMOD_MASK) + { + #ifdef SUPPORT_INPUTYUV444 + case F_MODE_YUV444: + ErrorF("Input mode is YUV444 ") ; + switch(bOutputMode&F_MODE_CLRMOD_MASK) + { + case F_MODE_YUV444: + ErrorF("Output mode is YUV444\n") ; + csc = B_CSC_BYPASS ; + break ; + + case F_MODE_YUV422: + ErrorF("Output mode is YUV422\n") ; + if(bInputMode & F_MODE_EN_UDFILT) // YUV444 to YUV422 need up/down filter for processing. + { + filter |= B_TX_EN_UDFILTER ; + } + csc = B_CSC_BYPASS ; + break ; + case F_MODE_RGB444: + ErrorF("Output mode is RGB24\n") ; + csc = B_CSC_YUV2RGB ; + if(bInputMode & F_MODE_EN_DITHER) // YUV444 to RGB24 need dither + { + filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; + } + + break ; + } + break ; + #endif + + #ifdef SUPPORT_INPUTYUV422 + case F_MODE_YUV422: + ErrorF("Input mode is YUV422\n") ; + switch(bOutputMode&F_MODE_CLRMOD_MASK) + { + case F_MODE_YUV444: + ErrorF("Output mode is YUV444\n") ; + csc = B_CSC_BYPASS ; + if(bInputMode & F_MODE_EN_UDFILT) // YUV422 to YUV444 need up filter + { + filter |= B_TX_EN_UDFILTER ; + } + + if(bInputMode & F_MODE_EN_DITHER) // YUV422 to YUV444 need dither + { + filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; + } + + break ; + case F_MODE_YUV422: + ErrorF("Output mode is YUV422\n") ; + csc = B_CSC_BYPASS ; + + break ; + + case F_MODE_RGB444: + ErrorF("Output mode is RGB24\n") ; + csc = B_CSC_YUV2RGB ; + if(bInputMode & F_MODE_EN_UDFILT) // YUV422 to RGB24 need up/dn filter. + { + filter |= B_TX_EN_UDFILTER ; + } + + if(bInputMode & F_MODE_EN_DITHER) // YUV422 to RGB24 need dither + { + filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; + } + + break ; + } + break ; + #endif + + #ifdef SUPPORT_INPUTRGB + case F_MODE_RGB444: + ErrorF("Input mode is RGB24\n") ; + switch(bOutputMode&F_MODE_CLRMOD_MASK) + { + case F_MODE_YUV444: + ErrorF("Output mode is YUV444\n") ; + csc = B_CSC_RGB2YUV ; + + if(bInputMode & F_MODE_EN_DITHER) // RGB24 to YUV444 need dither + { + filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; + } + break ; + + case F_MODE_YUV422: + ErrorF("Output mode is YUV422\n") ; + if(bInputMode & F_MODE_EN_UDFILT) // RGB24 to YUV422 need down filter. + { + filter |= B_TX_EN_UDFILTER ; + } + + if(bInputMode & F_MODE_EN_DITHER) // RGB24 to YUV422 need dither + { + filter |= B_TX_EN_DITHER | B_TX_DNFREE_GO ; + } + csc = B_CSC_RGB2YUV ; + break ; + + case F_MODE_RGB444: + ErrorF("Output mode is RGB24\n") ; + csc = B_CSC_BYPASS ; + break ; + } + break ; + #endif + } + + #ifdef SUPPORT_INPUTRGB + // set the CSC metrix registers by colorimetry and quantization + if(csc == B_CSC_RGB2YUV) + { + ErrorF("CSC = RGB2YUV %x ",csc) ; + switch(bInputMode&(F_MODE_ITU709|F_MODE_16_235)) + { + case F_MODE_ITU709|F_MODE_16_235: + ErrorF("ITU709 16-235 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU709_16_235,SIZEOF_CSCMTX) ; + break ; + case F_MODE_ITU709|F_MODE_0_255: + ErrorF("ITU709 0-255 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU709_0_255,SIZEOF_CSCMTX) ; + break ; + case F_MODE_ITU601|F_MODE_16_235: + ErrorF("ITU601 16-235 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU601_16_235,SIZEOF_CSCMTX) ; + break ; + case F_MODE_ITU601|F_MODE_0_255: + default: + ErrorF("ITU601 0-255 ") ; + + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_RGB2YUV_ITU601_0_255,SIZEOF_CSCMTX) ; + break ; + } + + } + #endif + + #ifdef SUPPORT_INPUTYUV + if (csc == B_CSC_YUV2RGB) + { + int i; + ErrorF("CSC = YUV2RGB %x ",csc) ; + + switch(bInputMode&(F_MODE_ITU709|F_MODE_16_235)) + { + case F_MODE_ITU709|F_MODE_16_235: + ErrorF("ITU709 16-235 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU709_16_235,SIZEOF_CSCMTX) ; + break ; + case F_MODE_ITU709|F_MODE_0_255: + ErrorF("ITU709 0-255 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU709_0_255,SIZEOF_CSCMTX) ; + break ; + case F_MODE_ITU601|F_MODE_16_235: + ErrorF("ITU601 16-235 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_16_235,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU601_16_235,SIZEOF_CSCMTX) ; + break ; + case F_MODE_ITU601|F_MODE_0_255: + default: + //????? debug + ErrorF("ITU601 0-255 ") ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_YOFF,bCSCOffset_0_255,SIZEOF_CSCOFFSET) ; + HDMITX_WriteI2C_ByteN(REG_TX_CSC_MTX11_L,bCSCMtx_YUV2RGB_ITU601_0_255,SIZEOF_CSCMTX) ; + break ; + } + } + #endif + + ucData = HDMITX_ReadI2C_Byte(REG_TX_CSC_CTRL) & ~(M_CSC_SEL|B_TX_DNFREE_GO|B_TX_EN_DITHER|B_TX_EN_UDFILTER) ; + ucData |= filter|csc ; + HDMITX_WriteI2C_Byte(REG_TX_CSC_CTRL,ucData) ; + // set output Up/Down Filter,Dither control + +} + + +////////////////////////////////////////////////////////////////////// +// Function: SetupAFE +// Parameter: VIDEOPCLKLEVEL level +// PCLK_LOW - for 13.5MHz (for mode less than 1080p) +// PCLK MEDIUM - for 25MHz~74MHz +// PCLK HIGH - PCLK > 80Hz (for 1080p mode or above) +// Return: N/A +// Remark: set reg62~reg65 depended on HighFreqMode +// reg61 have to be programmed at last and after video stable input. +// Side-Effect: +////////////////////////////////////////////////////////////////////// + +static void +// SetupAFE(BYTE ucFreqInMHz) +SetupAFE(VIDEOPCLKLEVEL level) +{ + // @emily turn off reg61 before SetupAFE parameters. + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,B_AFE_DRV_RST) ;/* 0x10 */ + // HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,0x3) ; + ErrorF("SetupAFE()\n") ; + + //TMDS Clock < 80MHz TMDS Clock > 80MHz + //Reg61 0x03 0x03 + + //Reg62 0x18 0x88 + //Reg63 Default Default + //Reg64 0x08 0x80 + //Reg65 Default Default + //Reg66 Default Default + //Reg67 Default Default + + switch(level) + { + case PCLK_HIGH: + HDMITX_WriteI2C_Byte(REG_TX_AFE_XP_CTRL,0x88) ; // reg62 + HDMITX_WriteI2C_Byte(REG_TX_AFE_ISW_CTRL, 0x10) ; // reg63 + HDMITX_WriteI2C_Byte(REG_TX_AFE_IP_CTRL,0x84) ; // reg64 + break ; + default: + HDMITX_WriteI2C_Byte(REG_TX_AFE_XP_CTRL,0x18) ; // reg62 + HDMITX_WriteI2C_Byte(REG_TX_AFE_ISW_CTRL, 0x10) ; // reg63 + HDMITX_WriteI2C_Byte(REG_TX_AFE_IP_CTRL,0x0C) ; // reg64 + break ; + } + //HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_REF_RST|B_VID_RST|B_AREF_RST|B_HDMI_RST)) ; + DelayMS(1) ; + HDMITX_AndREG_Byte(REG_TX_SW_RST,B_VID_RST|B_AREF_RST|B_AUD_RST|B_HDCP_RST) ; + DelayMS(100) ; + HDMITX_AndREG_Byte(REG_TX_SW_RST, B_AREF_RST|B_AUD_RST|B_HDCP_RST) ; + // REG_TX_AFE_DRV_CTRL have to be set at the last step of setup . +} + + +////////////////////////////////////////////////////////////////////// +// Function: FireAFE +// Parameter: N/A +// Return: N/A +// Remark: write reg61 with 0x04 +// When program reg61 with 0x04,then audio and video circuit work. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// +static void +FireAFE() +{ + BYTE reg; + Switch_HDMITX_Bank(0) ; + + HDMITX_WriteI2C_Byte(REG_TX_AFE_DRV_CTRL,0) ; + + for(reg = 0x61 ; reg <= 0x67 ; reg++) + { + ErrorF("Reg[%02X] = %02X\n",reg,HDMITX_ReadI2C_Byte(reg)) ; + } +} + +////////////////////////////////////////////////////////////////////// +// Audio Output +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// Function: SetAudioFormat +// Parameter: +// NumChannel - number of channel,from 1 to 8 +// AudioEnable - Audio source and type bit field,value of bit field are +// ENABLE_SPDIF (1<<4) +// ENABLE_I2S_SRC3 (1<<3) +// ENABLE_I2S_SRC2 (1<<2) +// ENABLE_I2S_SRC1 (1<<1) +// ENABLE_I2S_SRC0 (1<<0) +// SampleFreq - the audio sample frequence in Hz +// AudSWL - Audio sample width,only support 16,18,20,or 24. +// AudioCatCode - The audio channel catalogy code defined in IEC 60958-3 +// Return: ER_SUCCESS if done,ER_FAIL for otherwise. +// Remark: program audio channel control register and audio channel registers +// to enable audio by input. +// Side-Effect: register bank will keep in bank zero. +////////////////////////////////////////////////////////////////////// + + +static SYS_STATUS +SetAudioFormat(BYTE NumChannel,BYTE AudioEnable,BYTE bSampleFreq,BYTE AudSWL,BYTE AudioCatCode) +{ + BYTE fs = bSampleFreq ; + BYTE SWL ; + + BYTE SourceValid ; + BYTE SoruceNum ; + + + ErrorF("SetAudioFormat(%d channel,%02X,SampleFreq %d,AudSWL %d,%02X)\n",NumChannel,AudioEnable,bSampleFreq,AudSWL,AudioCatCode) ; + + +//richard remove Instance[0].bOutputAudioMode |= 0x41 ; + if(NumChannel > 6) + { + SourceValid = B_AUD_ERR2FLAT | B_AUD_S3VALID | B_AUD_S2VALID | B_AUD_S1VALID ; + SoruceNum = 4 ; + } + else if (NumChannel > 4) + { + SourceValid = B_AUD_ERR2FLAT | B_AUD_S2VALID | B_AUD_S1VALID ; + SoruceNum = 3 ; + } + else if (NumChannel > 2) + { + SourceValid = B_AUD_ERR2FLAT | B_AUD_S1VALID ; + SoruceNum = 2 ; + } + else + { + SourceValid = B_AUD_ERR2FLAT ; // only two channel. + SoruceNum = 1 ; + Instance[0].bOutputAudioMode &= ~0x40 ; + } + + AudioEnable &= ~ (M_AUD_SWL|B_SPDIFTC) ; + + switch(AudSWL) + { + case 16: + SWL = AUD_SWL_16 ; + AudioEnable |= M_AUD_16BIT ; + break ; + case 18: + SWL = AUD_SWL_18 ; + AudioEnable |= M_AUD_18BIT ; + break ; + case 20: + SWL = AUD_SWL_20 ; + AudioEnable |= M_AUD_20BIT ; + break ; + case 24: + SWL = AUD_SWL_24 ; + AudioEnable |= M_AUD_24BIT ; + break ; + default: + return ER_FAIL ; + } + + + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable&0xF0) ; + + HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_AUD_RST|B_AREF_RST)) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL1,Instance[0].bOutputAudioMode) ; // regE1 bOutputAudioMode should be loaded from ROM image. + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_FIFOMAP,0xE4) ; // default mapping. + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL3,(Instance[0].bAudioChannelSwap&0xF)|(AudioEnable&B_AUD_SPDIF)) ; + HDMITX_WriteI2C_Byte(REG_TX_AUD_SRCVALID_FLAT,SourceValid) ; + + // suggested to be 0x41 + +// Switch_HDMITX_Bank(1) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_MODE,0 |((NumChannel == 1)?1:0)) ; // 2 audio channel without pre-emphasis,if NumChannel set it as 1. +// HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CAT,AudioCatCode) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_SRCNUM,SoruceNum) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUD0CHST_CHTNUM,0x21) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUD1CHST_CHTNUM,0x43) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUD2CHST_CHTNUM,0x65) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUD3CHST_CHTNUM,0x87) ; +// HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|fs) ; // choose clock +// fs = ~fs ; // OFS is the one's complement of FS +// HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,(fs<<4)|SWL) ; +// Switch_HDMITX_Bank(0) ; + + Switch_HDMITX_Bank(1) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_MODE,0 |((NumChannel == 1)?1:0)) ; // 2 audio channel without pre-emphasis,if NumChannel set it as 1. + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CAT,AudioCatCode) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_SRCNUM,SoruceNum) ; + HDMITX_WriteI2C_Byte(REG_TX_AUD0CHST_CHTNUM,0) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|fs) ; // choose clock + fs = ~fs ; // OFS is the one's complement of FS + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,(fs<<4)|SWL) ; + Switch_HDMITX_Bank(0) ; + + // richard modify (could be bug), if(!(AudioEnable | B_AUD_SPDIF)) + if(!(AudioEnable & B_AUD_SPDIF)) + { + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0,AudioEnable) ; + } + + Instance[0].bAudioChannelEnable = AudioEnable ; + + // HDMITX_AndREG_Byte(REG_TX_SW_RST,B_AUD_RST) ; // enable Audio + return ER_SUCCESS; +} + + + +static void +AutoAdjustAudio() +{ + unsigned long SampleFreq ; + unsigned long N ; + unsigned long CTS ; + BYTE fs, uc ; + +// bPendingAdjustAudioFreq = TRUE ; + +// if( CAT6611_AudioChannelEnable & B_AUD_SPDIF ) +// { +// if(!(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_OSF_LOCK)) +// { +// return ; +// } +// } + + Switch_HDMITX_Bank(1) ; + + N = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN2)&0xF) << 16 ; + N |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN1)) <<8 ; + N |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudN0)) ; + + CTS = ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt2)&0xF) << 16 ; + CTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt1)) <<8 ; + CTS |= ((unsigned long)HDMITX_ReadI2C_Byte(REGPktAudCTSCnt0)) ; + Switch_HDMITX_Bank(0) ; + + // CTS = TMDSCLK * N / ( 128 * SampleFreq ) + // SampleFreq = TMDSCLK * N / (128*CTS) + + if( CTS == 0 ) + { + return ; + } + + SampleFreq = Instance[0].TMDSClock/CTS ; + SampleFreq *= N ; + SampleFreq /= 128 ; + + if( SampleFreq>31000 && SampleFreq<=38050 ) + { + Instance[0].bAudFs = AUDFS_32KHz ; + fs = AUDFS_32KHz ;; + } + else if (SampleFreq < 46050 ) // 44.1KHz + { + Instance[0].bAudFs = AUDFS_44p1KHz ; + fs = AUDFS_44p1KHz ;; + } + else if (SampleFreq < 68100 ) // 48KHz + { + Instance[0].bAudFs = AUDFS_48KHz ; + fs = AUDFS_48KHz ;; + } + else if (SampleFreq < 92100 ) // 88.2 KHz + { + Instance[0].bAudFs = AUDFS_88p2KHz ; + fs = AUDFS_88p2KHz ;; + } + else if (SampleFreq < 136200 ) // 96KHz + { + Instance[0].bAudFs = AUDFS_96KHz ; + fs = AUDFS_96KHz ;; + } + else if (SampleFreq < 184200 ) // 176.4KHz + { + Instance[0].bAudFs = AUDFS_176p4KHz ; + fs = AUDFS_176p4KHz ;; + } + else if (SampleFreq < 240200 ) // 192KHz + { + Instance[0].bAudFs = AUDFS_192KHz ; + fs = AUDFS_192KHz ;; + } + else + { + Instance[0].bAudFs = AUDFS_OTHER; + fs = AUDFS_OTHER;; + } + +// bPendingAdjustAudioFreq = FALSE ; + + SetNCTS(Instance[0].TMDSClock, Instance[0].bAudFs) ; // set N, CTS by new generated clock. + + Switch_HDMITX_Bank(1) ; // adjust the new fs in channel status registers + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_CA_FS,0x00|fs) ; // choose clock + fs = ~fs ; // OFS is the one's complement of FS + uc = HDMITX_ReadI2C_Byte(REG_TX_AUDCHST_OFS_WL) ; + uc &= 0xF ; + uc |= fs << 4 ; + HDMITX_WriteI2C_Byte(REG_TX_AUDCHST_OFS_WL,uc) ; + + Switch_HDMITX_Bank(0) ; + +} + +static void +SetupAudioChannel() +{ + static BYTE bEnableAudioChannel=FALSE ; + if( (HDMITX_ReadI2C_Byte(REG_TX_SW_RST) & (B_AUD_RST|B_AREF_RST)) == 0) // audio enabled + { + Switch_HDMITX_Bank(0) ; + + if((HDMITX_ReadI2C_Byte(REG_TX_AUDIO_CTRL0) & 0xf) == 0) + { + if(HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_OSF_LOCK) + { + SetNCTS(Instance[0].TMDSClock, Instance[0].bAudFs) ; // to enable automatic progress setting for N/CTS + DelayMS(5); + AutoAdjustAudio() ; + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, Instance[0].bAudioChannelEnable) ; + bEnableAudioChannel=TRUE ; + } + } + else + { + if((HDMITX_ReadI2C_Byte(REG_TX_CLK_STATUS2) & B_OSF_LOCK)==0) + { + // AutoAdjustAudio() ; + // ForceSetNCTS(CurrentPCLK, CurrentSampleFreq) ; + if( bEnableAudioChannel == TRUE ) + { + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(REG_TX_AUDIO_CTRL0, Instance[0].bAudioChannelEnable&0xF0) ; + } + bEnableAudioChannel=FALSE ; + } + } + } +} +////////////////////////////////////////////////////////////////////// +// Function: SetNCTS +// Parameter: PCLK - video clock in Hz. +// Fs - audio sample frequency in Hz +// Return: ER_SUCCESS if success +// Remark: set N value,the CTS will be auto generated by HW. +// Side-Effect: register bank will reset to bank 0. +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +SetNCTS(ULONG PCLK,ULONG Fs) +{ + ULONG n,MCLK ; + + MCLK = Fs * 256 ; // MCLK = fs * 256 ; + + ErrorF("SetNCTS(%ld,%ld): MCLK = %ld\n",PCLK,Fs,MCLK) ; + + if( PCLK ) + { + switch (Fs) { + case AUDFS_32KHz: + switch (PCLK) { + case 74175000: n = 11648; break; + case 14835000: n = 11648; break; + default: n = 4096; + } + break; + case AUDFS_44p1KHz: + switch (PCLK) { + case 74175000: n = 17836; break; + case 14835000: n = 8918; break; + default: n = 6272; + } + break; + case AUDFS_48KHz: + switch (PCLK) { + case 74175000: n = 11648; break; + case 14835000: n = 5824; break; + default: n = 6144; + } + break; + case AUDFS_88p2KHz: + switch (PCLK) { + case 74175000: n = 35672; break; + case 14835000: n = 17836; break; + default: n = 12544; + } + break; + case AUDFS_96KHz: + switch (PCLK) { + case 74175000: n = 23296; break; + case 14835000: n = 11648; break; + default: n = 12288; + } + break; + case AUDFS_176p4KHz: + switch (PCLK) { + case 74175000: n = 71344; break; + case 14835000: n = 35672; break; + default: n = 25088; + } + break; + case AUDFS_192KHz: + switch (PCLK) { + case 74175000: n = 46592; break; + case 14835000: n = 23296; break; + default: n = 24576; + } + break; + default: n = MCLK / 2000; + } + } + else + { + switch(Fs) + { + case AUDFS_32KHz: n = 4096; break; + case AUDFS_44p1KHz: n = 6272; break; + case AUDFS_48KHz: n = 6144; break; + case AUDFS_88p2KHz: n = 12544; break; + case AUDFS_96KHz: n = 12288; break; + case AUDFS_176p4KHz: n = 25088; break; + case AUDFS_192KHz: n = 24576; break; + default: n = 6144; + } + + } + + + ErrorF("N = %ld\n",n) ; + Switch_HDMITX_Bank(1) ; + HDMITX_WriteI2C_Byte(REGPktAudN0,(BYTE)((n)&0xFF)) ; + HDMITX_WriteI2C_Byte(REGPktAudN1,(BYTE)((n>>8)&0xFF)) ; + HDMITX_WriteI2C_Byte(REGPktAudN2,(BYTE)((n>>16)&0xF)) ; + Switch_HDMITX_Bank(0) ; + + HDMITX_WriteI2C_Byte(REG_TX_PKT_SINGLE_CTRL,0) ; // D[1] = 0,HW auto count CTS + + HDMITX_SetREG_Byte(REG_TX_CLK_CTRL0,~M_EXT_MCLK_SEL,B_EXT_256FS) ; + return ER_SUCCESS ; +} + +////////////////////////////////////////////////////////////////////// +// DDC Function. +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////// +// Function: ClearDDCFIFO +// Parameter: N/A +// Return: N/A +// Remark: clear the DDC FIFO. +// Side-Effect: DDC master will set to be HOST. +////////////////////////////////////////////////////////////////////// + +static void +ClearDDCFIFO() +{ + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_FIFO_CLR) ; +} + +static void +GenerateDDCSCLK() +{ + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_GEN_SCLCLK) ; +} +////////////////////////////////////////////////////////////////////// +// Function: AbortDDC +// Parameter: N/A +// Return: N/A +// Remark: Force abort DDC and reset DDC bus. +// Side-Effect: +////////////////////////////////////////////////////////////////////// + +static void +AbortDDC() +{ + BYTE CPDesire,SWReset,DDCMaster ; + BYTE uc, timeout ; + // save the SW reset,DDC master,and CP Desire setting. + SWReset = HDMITX_ReadI2C_Byte(REG_TX_SW_RST) ; + CPDesire = HDMITX_ReadI2C_Byte(REG_TX_HDCP_DESIRE) ; + DDCMaster = HDMITX_ReadI2C_Byte(REG_TX_DDC_MASTER_CTRL) ; + + + HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,CPDesire&(~B_CPDESIRE)) ; // @emily change order + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,SWReset|B_HDCP_RST) ; // @emily change order + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_ABORT) ; + + for( timeout = 0 ; timeout < 200 ; timeout++ ) + { + uc = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + if (uc&B_DDC_DONE) + { + break ; // success + } + + if( uc & (B_DDC_NOACK|B_DDC_WAITBUS|B_DDC_ARBILOSE) ) + { + ErrorF("AbortDDC Fail by reg16=%02X\n",uc) ; + break ; + } + DelayMS(1) ; // delay 1 ms to stable. + } + + // restore the SW reset,DDC master,and CP Desire setting. + HDMITX_WriteI2C_Byte(REG_TX_SW_RST,SWReset) ; + HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,CPDesire) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,DDCMaster) ; +} + +////////////////////////////////////////////////////////////////////// +// Packet and InfoFrame +////////////////////////////////////////////////////////////////////// + +// //////////////////////////////////////////////////////////////////////////////// +// // Function: SetAVMute() +// // Parameter: N/A +// // Return: N/A +// // Remark: set AVMute as TRUE and enable GCP sending. +// // Side-Effect: N/A +// //////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// void +// SetAVMute() +// { +// Switch_HDMITX_Bank(0) ; +// HDMITX_WriteI2C_Byte(REG_TX_GCP,B_SET_AVMUTE) ; +// HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT) ; +// } + +// //////////////////////////////////////////////////////////////////////////////// +// // Function: SetAVMute(FALSE) +// // Parameter: N/A +// // Return: N/A +// // Remark: clear AVMute as TRUE and enable GCP sending. +// // Side-Effect: N/A +// //////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// void +// SetAVMute(FALSE) +// { +// Switch_HDMITX_Bank(0) ; +// HDMITX_WriteI2C_Byte(REG_TX_GCP,B_CLR_AVMUTE) ; +// HDMITX_WriteI2C_Byte(REG_TX_PKT_GENERAL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT) ; +// } + + + +////////////////////////////////////////////////////////////////////// +// Function: ReadEDID +// Parameter: pData - the pointer of buffer to receive EDID ucdata. +// bSegment - the segment of EDID readback. +// offset - the offset of EDID ucdata in the segment. in byte. +// count - the read back bytes count,cannot exceed 32 +// Return: ER_SUCCESS if successfully getting EDID. ER_FAIL otherwise. +// Remark: function for read EDID ucdata from reciever. +// Side-Effect: DDC master will set to be HOST. DDC FIFO will be used and dirty. +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +ReadEDID(BYTE *pData,BYTE bSegment,BYTE offset,SHORT Count) +{ + SHORT RemainedCount,ReqCount ; + BYTE bCurrOffset ; + SHORT TimeOut ; + BYTE *pBuff = pData ; + BYTE ucdata ; + + // ErrorF("ReadEDID(%08lX,%d,%d,%d)\n",(ULONG)pData,bSegment,offset,Count) ; + if(!pData) + { + ErrorF("ReadEDID(): Invallid pData pointer %08lX\n",(ULONG)pData) ; + return ER_FAIL ; + } + + if(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_INT_DDC_BUS_HANG) + { + ErrorF("Called AboutDDC()\n") ; + AbortDDC() ; + + } + + ClearDDCFIFO() ; + + RemainedCount = Count ; + bCurrOffset = offset ; + + Switch_HDMITX_Bank(0) ; + + while(RemainedCount > 0) + { + + ReqCount = (RemainedCount > DDC_FIFO_MAXREQ)?DDC_FIFO_MAXREQ:RemainedCount ; + ErrorF("ReadEDID(): ReqCount = %d,bCurrOffset = %d\n",ReqCount,bCurrOffset) ; + + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_FIFO_CLR) ; + + for(TimeOut = 0 ; TimeOut < 200 ; TimeOut++) + { + ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + + if(ucdata&B_DDC_DONE) + { + break ; + } + + if((ucdata & B_DDC_ERROR)||(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_INT_DDC_BUS_HANG)) + { + ErrorF("Called AboutDDC()\n") ; + AbortDDC() ; + return ER_FAIL ; + } + } + + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_EDID_ADDRESS) ; // for EDID ucdata get + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,bCurrOffset) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,(BYTE)ReqCount) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_EDIDSEG,bSegment) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_EDID_READ) ; + + bCurrOffset += ReqCount ; + RemainedCount -= ReqCount ; + + for(TimeOut = 250 ; TimeOut > 0 ; TimeOut --) + { + DelayMS(1) ; + ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + if(ucdata & B_DDC_DONE) + { + break ; + } + + if(ucdata & B_DDC_ERROR) + { + ErrorF("ReadEDID(): DDC_STATUS = %02X,fail.\n",ucdata) ; + return ER_FAIL ; + } + } + + if(TimeOut == 0) + { + ErrorF("ReadEDID(): DDC TimeOut. \n",ucdata) ; + return ER_FAIL ; + } + + do + { + *(pBuff++) = HDMITX_ReadI2C_Byte(REG_TX_DDC_READFIFO) ; + ReqCount -- ; + }while(ReqCount > 0) ; + + } + + return ER_SUCCESS ; +} + + + +#ifdef SUPPORT_HDCP +////////////////////////////////////////////////////////////////////// +// Authentication +////////////////////////////////////////////////////////////////////// +static void +HDCP_ClearAuthInterrupt() +{ + BYTE uc ; + uc = HDMITX_ReadI2C_Byte(REG_TX_INT_MASK2) & (~(B_KSVLISTCHK_MASK|B_T_AUTH_DONE_MASK|B_AUTH_FAIL_MASK)); + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_FAIL|B_CLR_AUTH_DONE|B_CLR_KSVLISTCHK) ; + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; +} + +static void +HDCP_ResetAuth() +{ + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0) ; + HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,0) ; + HDMITX_OrREG_Byte(REG_TX_SW_RST,B_HDCP_RST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDCP_ClearAuthInterrupt() ; + AbortDDC() ; +} +////////////////////////////////////////////////////////////////////// +// Function: HDCP_EnableEncryption +// Parameter: N/A +// Return: ER_SUCCESS if done. +// Remark: Set regC1 as zero to enable continue authentication. +// Side-Effect: register bank will reset to zero. +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +HDCP_EnableEncryption() +{ + Switch_HDMITX_Bank(0) ; + return HDMITX_WriteI2C_Byte(REG_TX_ENCRYPTION,B_ENABLE_ENCRYPTION); +} + + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_Auth_Fire() +// Parameter: N/A +// Return: N/A +// Remark: write anything to reg21 to enable HDCP authentication by HW +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static void +HDCP_Auth_Fire() +{ + // ErrorF("HDCP_Auth_Fire():\n") ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHDCP) ; // MASTERHDCP,no need command but fire. + HDMITX_WriteI2C_Byte(REG_TX_AUTHFIRE,1); +} + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_StartAnCipher +// Parameter: N/A +// Return: N/A +// Remark: Start the Cipher to free run for random number. When stop,An is +// ready in Reg30. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static void +HDCP_StartAnCipher() +{ + HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_START_CIPHER_GEN) ; + DelayMS(1) ; // delay 1 ms +} + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_StopAnCipher +// Parameter: N/A +// Return: N/A +// Remark: Stop the Cipher,and An is ready in Reg30. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static void +HDCP_StopAnCipher() +{ + HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_STOP_CIPHER_GEN) ; +} + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_GenerateAn +// Parameter: N/A +// Return: N/A +// Remark: start An ciper random run at first,then stop it. Software can get +// an in reg30~reg38,the write to reg28~2F +// Side-Effect: +////////////////////////////////////////////////////////////////////// + +static void +HDCP_GenerateAn() +{ + BYTE Data[8] ; + + HDCP_StartAnCipher() ; + // HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_START_CIPHER_GEN) ; + // DelayMS(1) ; // delay 1 ms + // HDMITX_WriteI2C_Byte(REG_TX_AN_GENERATE,B_STOP_CIPHER_GEN) ; + + HDCP_StopAnCipher() ; + + Switch_HDMITX_Bank(0) ; + // new An is ready in reg30 + HDMITX_ReadI2C_ByteN(REG_TX_AN_GEN,Data,8) ; + HDMITX_WriteI2C_ByteN(REG_TX_AN,Data,8) ; + +} + + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_GetBCaps +// Parameter: pBCaps - pointer of byte to get BCaps. +// pBStatus - pointer of two bytes to get BStatus +// Return: ER_SUCCESS if successfully got BCaps and BStatus. +// Remark: get B status and capability from HDCP reciever via DDC bus. +// Side-Effect: +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +HDCP_GetBCaps(PBYTE pBCaps ,PUSHORT pBStatus) +{ + BYTE ucdata ; + BYTE TimeOut ; + + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_HDCP_ADDRESS) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x40) ; // BCaps offset + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,3) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; + + for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) + { + DelayMS(1) ; + + ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + if(ucdata & B_DDC_DONE) + { + //ErrorF("HDCP_GetBCaps(): DDC Done.\n") ; + break ; + } + + if(ucdata & B_DDC_ERROR) + { + ErrorF("HDCP_GetBCaps(): DDC fail by reg16=%02X.\n",ucdata) ; + return ER_FAIL ; + } + } + + if(TimeOut == 0) + { + return ER_FAIL ; + } + + HDMITX_ReadI2C_ByteN(REG_TX_BSTAT,(PBYTE)pBStatus,2) ; + *pBCaps = HDMITX_ReadI2C_Byte(REG_TX_BCAP) ; + return ER_SUCCESS ; + +} + + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_GetBKSV +// Parameter: pBKSV - pointer of 5 bytes buffer for getting BKSV +// Return: ER_SUCCESS if successfuly got BKSV from Rx. +// Remark: Get BKSV from HDCP reciever. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +HDCP_GetBKSV(BYTE *pBKSV) +{ + BYTE ucdata ; + BYTE TimeOut ; + + Switch_HDMITX_Bank(0) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,DDC_HDCP_ADDRESS) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x00) ; // BKSV offset + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,5) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; + + for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) + { + DelayMS(1) ; + + ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + if(ucdata & B_DDC_DONE) + { + ErrorF("HDCP_GetBCaps(): DDC Done.\n") ; + break ; + } + + if(ucdata & B_DDC_ERROR) + { + ErrorF("HDCP_GetBCaps(): DDC No ack or arbilose,%x,maybe cable did not connected. Fail.\n",ucdata) ; + return ER_FAIL ; + } + } + + if(TimeOut == 0) + { + return ER_FAIL ; + } + + HDMITX_ReadI2C_ByteN(REG_TX_BKSV,(PBYTE)pBKSV,5) ; + + return ER_SUCCESS ; +} + +////////////////////////////////////////////////////////////////////// +// Function:HDCP_Authenticate +// Parameter: N/A +// Return: ER_SUCCESS if Authenticated without error. +// Remark: do Authentication with Rx +// Side-Effect: +// 1. Instance[0].bAuthenticated global variable will be TRUE when authenticated. +// 2. Auth_done interrupt and AUTH_FAIL interrupt will be enabled. +////////////////////////////////////////////////////////////////////// +static BYTE +countbit(BYTE b) +{ + BYTE i,count ; + for( i = 0, count = 0 ; i < 8 ; i++ ) + { + if( b & (1< 6) + { + ErrorF("Down Stream Count %d is over maximum supported number 6,fail.\n",(BStatus & M_DOWNSTREAM_COUNT)) ; + return ER_FAIL ; + } + */ + + HDCP_GetBKSV(BKSV) ; + ErrorF("BKSV %02X %02X %02X %02X %02X\n",BKSV[0],BKSV[1],BKSV[2],BKSV[3],BKSV[4]) ; + + for(TimeOut = 0, ucdata = 0 ; TimeOut < 5 ; TimeOut ++) + { + ucdata += countbit(BKSV[TimeOut]) ; + } + if( ucdata != 20 ) return ER_FAIL ; + + + #ifdef SUPPORT_REVOKE_KSV + HDCP_VerifyRevocationList(SRM1,BKSV,&revoked) ; + if(revoked) + { + ErrorF("BKSV is revoked\n") ; return ER_FAIL ; + } + ErrorF("BKSV %02X %02X %02X %02X %02X is NOT %srevoked\n",BKSV[0],BKSV[1],BKSV[2],BKSV[3],BKSV[4],revoked?"not ":"") ; + #endif // SUPPORT_DSSSHA + + Switch_HDMITX_Bank(0) ; // switch bank action should start on direct register writting of each function. + + // 2006/08/11 added by jjtseng + // enable HDCP on CPDired enabled. + HDMITX_AndREG_Byte(REG_TX_SW_RST,~(B_HDCP_RST)) ; + //~jjtseng 2006/08/11 + +// if(BCaps & B_CAP_HDCP_1p1) +// { +// ErrorF("RX support HDCP 1.1\n") ; +// HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,B_ENABLE_HDPC11|B_CPDESIRE) ; +// } +// else +// { +// ErrorF("RX not support HDCP 1.1\n") ; + HDMITX_WriteI2C_Byte(REG_TX_HDCP_DESIRE,B_CPDESIRE) ; +// } + + + // HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_DONE|B_CLR_AUTH_FAIL|B_CLR_KSVLISTCHK) ; + // HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; // don't clear other settings. + // ucdata = HDMITX_ReadI2C_Byte(REG_TX_SYS_STATUS) ; + // ucdata = (ucdata & M_CTSINTSTEP) | B_INTACTDONE ; + // HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,ucdata) ; // clear action. + + // HDMITX_AndREG_Byte(REG_TX_INT_MASK2,~(B_AUTH_FAIL_MASK|B_T_AUTH_DONE_MASK)) ; // enable GetBCaps Interrupt + HDCP_ClearAuthInterrupt() ; + ErrorF("int2 = %02X DDC_Status = %02X\n",HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2),HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS)) ; + + + HDCP_GenerateAn() ; + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,0) ; + Instance[0].bAuthenticated = FALSE ; + + if((BCaps & B_CAP_HDMI_REPEATER) == 0) + { + HDCP_Auth_Fire(); + // wait for status ; + + for(TimeOut = 250 ; TimeOut > 0 ; TimeOut --) + { + DelayMS(5) ; // delay 1ms + ucdata = HDMITX_ReadI2C_Byte(REG_TX_AUTH_STAT) ; + ErrorF("reg46 = %02x reg16 = %02x\n",ucdata,HDMITX_ReadI2C_Byte(0x16)) ; + + if(ucdata & B_T_AUTH_DONE) + { + Instance[0].bAuthenticated = TRUE ; + break ; + } + + ucdata = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2) ; + if(ucdata & B_INT_AUTH_FAIL) + { + /* + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_FAIL) ; + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; + */ + ErrorF("HDCP_Authenticate(): Authenticate fail\n") ; + Instance[0].bAuthenticated = FALSE ; + return ER_FAIL ; + } + } + + if(TimeOut == 0) + { + ErrorF("HDCP_Authenticate(): Time out. return fail\n") ; + Instance[0].bAuthenticated = FALSE ; + return ER_FAIL ; + } + return ER_SUCCESS ; + } + + return HDCP_Authenticate_Repeater() ; +} + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_VerifyIntegration +// Parameter: N/A +// Return: ER_SUCCESS if success,if AUTH_FAIL interrupt status,return fail. +// Remark: no used now. +// Side-Effect: +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +HDCP_VerifyIntegration() +{ + // richard BYTE ucdata ; + // if any interrupt issued a Auth fail,returned the Verify Integration fail. + + if(HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) & B_INT_AUTH_FAIL) + { + HDCP_ClearAuthInterrupt() ; + Instance[0].bAuthenticated = FALSE ; + return ER_FAIL ; + } + + if(Instance[0].bAuthenticated == TRUE) + { + return ER_SUCCESS ; + } + + return ER_FAIL ; +} + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_Authenticate_Repeater +// Parameter: BCaps and BStatus +// Return: ER_SUCCESS if success,if AUTH_FAIL interrupt status,return fail. +// Remark: +// Side-Effect: as Authentication +////////////////////////////////////////////////////////////////////// +static _XDATA BYTE KSVList[32] ; +static _XDATA BYTE Vr[20] ; +static _XDATA BYTE M0[8] ; + +static void +HDCP_CancelRepeaterAuthenticate() +{ + ErrorF("HDCP_CancelRepeaterAuthenticate") ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERDDC|B_MASTERHOST) ; + AbortDDC() ; + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,B_LISTFAIL|B_LISTDONE) ; + HDCP_ClearAuthInterrupt() ; +} + +static void +HDCP_ResumeRepeaterAuthenticate() +{ + HDMITX_WriteI2C_Byte(REG_TX_LISTCTRL,B_LISTDONE) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHDCP) ; +} + + +static SYS_STATUS +HDCP_GetKSVList(BYTE *pKSVList,BYTE cDownStream) +{ + BYTE TimeOut = 100 ; + BYTE ucdata ; + + if(cDownStream == 0 || pKSVList == NULL) + { + return ER_FAIL ; + } + + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,0x74) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x43) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,cDownStream * 5) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; + + + for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) + { + + ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + if(ucdata & B_DDC_DONE) + { + ErrorF("HDCP_GetKSVList(): DDC Done.\n") ; + break ; + } + + if(ucdata & B_DDC_ERROR) + { + ErrorF("HDCP_GetKSVList(): DDC Fail by REG_TX_DDC_STATUS = %x.\n",ucdata) ; + return ER_FAIL ; + } + DelayMS(5) ; + } + + if(TimeOut == 0) + { + return ER_FAIL ; + } + + ErrorF("HDCP_GetKSVList(): KSV") ; + for(TimeOut = 0 ; TimeOut < cDownStream * 5 ; TimeOut++) + { + pKSVList[TimeOut] = HDMITX_ReadI2C_Byte(REG_TX_DDC_READFIFO) ; + ErrorF(" %02X",pKSVList[TimeOut]) ; + } + ErrorF("\n") ; + return ER_SUCCESS ; +} + +static SYS_STATUS +HDCP_GetVr(BYTE *pVr) +{ + BYTE TimeOut ; + BYTE ucdata ; + + if(pVr == NULL) + { + // richard return NULL ; + return ER_FAIL; + } + + HDMITX_WriteI2C_Byte(REG_TX_DDC_MASTER_CTRL,B_MASTERHOST) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_HEADER,0x74) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQOFF,0x20) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_REQCOUNT,20) ; + HDMITX_WriteI2C_Byte(REG_TX_DDC_CMD,CMD_DDC_SEQ_BURSTREAD) ; + + + for(TimeOut = 200 ; TimeOut > 0 ; TimeOut --) + { + ucdata = HDMITX_ReadI2C_Byte(REG_TX_DDC_STATUS) ; + if(ucdata & B_DDC_DONE) + { + ErrorF("HDCP_GetVr(): DDC Done.\n") ; + break ; + } + + if(ucdata & B_DDC_ERROR) + { + ErrorF("HDCP_GetVr(): DDC fail by REG_TX_DDC_STATUS = %x.\n",ucdata) ; + return ER_FAIL ; + } + DelayMS(5) ; + } + + if(TimeOut == 0) + { + ErrorF("HDCP_GetVr(): DDC fail by timeout.\n",ucdata) ; + return ER_FAIL ; + } + + Switch_HDMITX_Bank(0) ; + + for(TimeOut = 0 ; TimeOut < 5 ; TimeOut++) + { + HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL ,TimeOut) ; + pVr[TimeOut*4+3] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE1) ; + pVr[TimeOut*4+2] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE2) ; + pVr[TimeOut*4+1] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE3) ; + pVr[TimeOut*4] = (ULONG)HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE4) ; + ErrorF("V' = %02X %02X %02X %02X\n",pVr[TimeOut*4],pVr[TimeOut*4+1],pVr[TimeOut*4+2],pVr[TimeOut*4+3]) ; + } + + return ER_SUCCESS ; +} + +static SYS_STATUS +HDCP_GetM0(BYTE *pM0) +{ + int i ; + + if(!pM0) + { + return ER_FAIL ; + } + + HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,5) ; // read m0[31:0] from reg51~reg54 + pM0[0] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE1) ; + pM0[1] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE2) ; + pM0[2] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE3) ; + pM0[3] = HDMITX_ReadI2C_Byte(REG_TX_SHA_RD_BYTE4) ; + HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,0) ; // read m0[39:32] from reg55 + pM0[4] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; + HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,1) ; // read m0[47:40] from reg55 + pM0[5] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; + HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,2) ; // read m0[55:48] from reg55 + pM0[6] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; + HDMITX_WriteI2C_Byte(REG_TX_SHA_SEL,3) ; // read m0[63:56] from reg55 + pM0[7] = HDMITX_ReadI2C_Byte(REG_TX_AKSV_RD_BYTE5) ; + + ErrorF("M[] =") ; + for(i = 0 ; i < 8 ; i++){ + ErrorF("0x%02x,",pM0[i]) ; + } + ErrorF("\n") ; + return ER_SUCCESS ; +} + +static _XDATA BYTE SHABuff[64] ; +static _XDATA BYTE V[20] ; + +static _XDATA ULONG w[80]; +static _XDATA ULONG sha[5] ; + +#define rol(x,y) (((x) << (y)) | (((ULONG)x) >> (32-y))) + +static void SHATransform(ULONG * h); // richard add +void SHATransform(ULONG * h) +{ + LONG t; + + + for (t = 16; t < 80; t++) { + ULONG tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]; + w[t] = rol(tmp,1); + printf("w[%2d] = %08lX\n",t,w[t]) ; + } + + h[0] = 0x67452301 ; + h[1] = 0xefcdab89; + h[2] = 0x98badcfe; + h[3] = 0x10325476; + h[4] = 0xc3d2e1f0; + + for (t = 0; t < 20; t++) { + ULONG tmp = + rol(h[0],5) + ((h[1] & h[2]) | (h[3] & ~h[1])) + h[4] + w[t] + 0x5a827999; + printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; + + h[4] = h[3]; + h[3] = h[2]; + h[2] = rol(h[1],30); + h[1] = h[0]; + h[0] = tmp; + + } + for (t = 20; t < 40; t++) { + ULONG tmp = rol(h[0],5) + (h[1] ^ h[2] ^ h[3]) + h[4] + w[t] + 0x6ed9eba1; + printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; + h[4] = h[3]; + h[3] = h[2]; + h[2] = rol(h[1],30); + h[1] = h[0]; + h[0] = tmp; + } + for (t = 40; t < 60; t++) { + ULONG tmp = rol(h[0], + 5) + ((h[1] & h[2]) | (h[1] & h[3]) | (h[2] & h[3])) + h[4] + w[t] + + 0x8f1bbcdc; + printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; + h[4] = h[3]; + h[3] = h[2]; + h[2] = rol(h[1],30); + h[1] = h[0]; + h[0] = tmp; + } + for (t = 60; t < 80; t++) { + ULONG tmp = rol(h[0],5) + (h[1] ^ h[2] ^ h[3]) + h[4] + w[t] + 0xca62c1d6; + printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; + h[4] = h[3]; + h[3] = h[2]; + h[2] = rol(h[1],30); + h[1] = h[0]; + h[0] = tmp; + } + printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; + + h[0] += 0x67452301 ; + h[1] += 0xefcdab89; + h[2] += 0x98badcfe; + h[3] += 0x10325476; + h[4] += 0xc3d2e1f0; + printf("%08lX %08lX %08lX %08lX %08lX\n",h[0],h[1],h[2],h[3],h[4]) ; +} + +/* ---------------------------------------------------------------------- + * Outer SHA algorithm: take an arbitrary length byte string, + * convert it into 16-word blocks with the prescribed padding at + * the end,and pass those blocks to the core SHA algorithm. + */ + + +void SHA_Simple(void *p,LONG len,BYTE *output) +{ + // SHA_State s; + int i, t ; + ULONG c ; + char *pBuff = p ; + + + for( i = 0 ; i < len ; i++ ) + { + t = i/4 ; + if( i%4 == 0 ) + { + w[t] = 0 ; + } + c = pBuff[i] ; + c <<= (3-(i%4))*8 ; + w[t] |= c ; + printf("pBuff[%d] = %02x, c = %08lX, w[%d] = %08lX\n",i,pBuff[i],c,t,w[t]) ; + } + t = i/4 ; + if( i%4 == 0 ) + { + w[t] = 0 ; + } + c = 0x80 << ((3-i%4)*24) ; + w[t]|= c ; t++ ; + for( ; t < 15 ; t++ ) + { + w[t] = 0 ; + } + w[15] = len*8 ; + + for( t = 0 ; t< 16 ; t++ ) + { + printf("w[%2d] = %08lX\n",t,w[t]) ; + } + + SHATransform(sha) ; + + for( i = 0 ; i < 5 ; i++ ) + { + output[i*4] = (BYTE)((sha[i]>>24)&0xFF) ; + output[i*4+1] = (BYTE)((sha[i]>>16)&0xFF) ; + output[i*4+2] = (BYTE)((sha[i]>>8)&0xFF) ; + output[i*4+3] = (BYTE)(sha[i]&0xFF) ; + } +} + +static SYS_STATUS +HDCP_CheckSHA(BYTE pM0[],USHORT BStatus,BYTE pKSVList[],int cDownStream,BYTE Vr[]) +{ + int i,n ; + + for(i = 0 ; i < cDownStream*5 ; i++) + { + SHABuff[i] = pKSVList[i] ; + } + SHABuff[i++] = BStatus & 0xFF ; + SHABuff[i++] = (BStatus>>8) & 0xFF ; + for(n = 0 ; n < 8 ; n++,i++) + { + SHABuff[i] = pM0[n] ; + } + n = i ; + // SHABuff[i++] = 0x80 ; // end mask + for(; i < 64 ; i++) + { + SHABuff[i] = 0 ; + } + // n = cDownStream * 5 + 2 /* for BStatus */ + 8 /* for M0 */ ; + // n *= 8 ; + // SHABuff[62] = (n>>8) & 0xff ; + // SHABuff[63] = (n>>8) & 0xff ; + for(i = 0 ; i < 64 ; i++) + { + if(i % 16 == 0) printf("SHA[]: ") ; + printf(" %02X",SHABuff[i]) ; + if((i%16)==15) printf("\n") ; + } + SHA_Simple(SHABuff,n,V) ; + printf("V[] =") ; + for(i = 0 ; i < 20 ; i++) + { + printf(" %02X",V[i]) ; + } + printf("\nVr[] =") ; + for(i = 0 ; i < 20 ; i++) + { + printf(" %02X",Vr[i]) ; + } + + for(i = 0 ; i < 20 ; i++) + { + if(V[i] != Vr[i]) + { + return ER_FAIL ; + } + } + return ER_SUCCESS ; +} + +static SYS_STATUS +HDCP_Authenticate_Repeater() +{ + BYTE uc ; + #ifdef SUPPORT_DSSSHA + BYTE revoked ; + int i ; + #else + int i; // richard add + BYTE revoked; // richard add + #endif // _DSS_SHA_ + // BYTE test; + // BYTE test06; + // BYTE test07; + // BYTE test08; + BYTE cDownStream ; + + BYTE BCaps; + USHORT BStatus ; + USHORT TimeOut ; + + ErrorF("Authentication for repeater\n") ; + // emily add for test,abort HDCP + // 2007/10/01 marked by jj_tseng@chipadvanced.com + // HDMITX_WriteI2C_Byte(0x20,0x00) ; + // HDMITX_WriteI2C_Byte(0x04,0x01) ; + // HDMITX_WriteI2C_Byte(0x10,0x01) ; + // HDMITX_WriteI2C_Byte(0x15,0x0F) ; + // DelayMS(100); + // HDMITX_WriteI2C_Byte(0x04,0x00) ; + // HDMITX_WriteI2C_Byte(0x10,0x00) ; + // HDMITX_WriteI2C_Byte(0x20,0x01) ; + // DelayMS(100); + // test07 = HDMITX_ReadI2C_Byte(0x7) ; + // test06 = HDMITX_ReadI2C_Byte(0x6); + // test08 = HDMITX_ReadI2C_Byte(0x8); + //~jj_tseng@chipadvanced.com + // end emily add for test + ////////////////////////////////////// + // Authenticate Fired + ////////////////////////////////////// + + HDCP_GetBCaps(&BCaps,&BStatus) ; + DelayMS(2); + HDCP_Auth_Fire(); + DelayMS(550); // emily add for test + + for(TimeOut = 250*6 ; TimeOut > 0 ; TimeOut --) + { + + uc = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT1) ; + if(uc & B_INT_DDC_BUS_HANG) + { + ErrorF("DDC Bus hang\n") ; + goto HDCP_Repeater_Fail ; + } + + uc = HDMITX_ReadI2C_Byte(REG_TX_INT_STAT2) ; + + if(uc & B_INT_AUTH_FAIL) + { + /* + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_AUTH_FAIL) ; + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; + */ + ErrorF("HDCP_Authenticate_Repeater(): B_INT_AUTH_FAIL.\n") ; + goto HDCP_Repeater_Fail ; + } + // emily add for test + // test =(HDMITX_ReadI2C_Byte(0x7)&0x4)>>2 ; + if(uc & B_INT_KSVLIST_CHK) + { + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR0,B_CLR_KSVLISTCHK) ; + HDMITX_WriteI2C_Byte(REG_TX_INT_CLR1,0) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,B_INTACTDONE) ; + HDMITX_WriteI2C_Byte(REG_TX_SYS_STATUS,0) ; + ErrorF("B_INT_KSVLIST_CHK\n") ; + break ; + } + + DelayMS(5) ; + } + + if(TimeOut == 0) + { + ErrorF("Time out for wait KSV List checking interrupt\n") ; + goto HDCP_Repeater_Fail ; + } + + /////////////////////////////////////// + // clear KSVList check interrupt. + /////////////////////////////////////// + + for(TimeOut = 500 ; TimeOut > 0 ; TimeOut --) + { + if((TimeOut % 100) == 0) + { + ErrorF("Wait KSV FIFO Ready %d\n",TimeOut) ; + } + + if(HDCP_GetBCaps(&BCaps,&BStatus) == ER_FAIL) + { + ErrorF("Get BCaps fail\n") ; + goto HDCP_Repeater_Fail ; + } + + if(BCaps & B_CAP_KSV_FIFO_RDY) + { + ErrorF("FIFO Ready\n") ; + break ; + } + DelayMS(5) ; + + } + + if(TimeOut == 0) + { + ErrorF("Get KSV FIFO ready TimeOut\n") ; + goto HDCP_Repeater_Fail ; + } + + ErrorF("Wait timeout = %d\n",TimeOut) ; + + ClearDDCFIFO() ; + GenerateDDCSCLK() ; + cDownStream = (BStatus & M_DOWNSTREAM_COUNT) ; + + if(cDownStream == 0 || cDownStream > 6 || BStatus & (B_MAX_CASCADE_EXCEEDED|B_DOWNSTREAM_OVER)) + { + ErrorF("Invalid Down stream count,fail\n") ; + goto HDCP_Repeater_Fail ; + } + + + if(HDCP_GetKSVList(KSVList,cDownStream) == ER_FAIL) + { + goto HDCP_Repeater_Fail ; + } + + for(i = 0 ; i < cDownStream ; i++) + { + revoked=FALSE ; uc = 0 ; + for( TimeOut = 0 ; TimeOut < 5 ; TimeOut++ ) + { + // check bit count + uc += countbit(KSVList[i*5+TimeOut]) ; + } + if( uc != 20 ) revoked = TRUE ; + #ifdef SUPPORT_REVOKE_KSV + HDCP_VerifyRevocationList(SRM1,&KSVList[i*5],&revoked) ; + #endif + if(revoked) + { + ErrorF("KSVFIFO[%d] = %02X %02X %02X %02X %02X is revoked\n",i,KSVList[i*5],KSVList[i*5+1],KSVList[i*5+2],KSVList[i*5+3],KSVList[i*5+4]) ; + goto HDCP_Repeater_Fail ; + } + } + + + if(HDCP_GetVr(Vr) == ER_FAIL) + { + goto HDCP_Repeater_Fail ; + } + + if(HDCP_GetM0(M0) == ER_FAIL) + { + goto HDCP_Repeater_Fail ; + } + + // do check SHA + if(HDCP_CheckSHA(M0,BStatus,KSVList,cDownStream,Vr) == ER_FAIL) + { + goto HDCP_Repeater_Fail ; + } + + + HDCP_ResumeRepeaterAuthenticate() ; + Instance[0].bAuthenticated = TRUE ; + return ER_SUCCESS ; + +HDCP_Repeater_Fail: + HDCP_CancelRepeaterAuthenticate() ; + return ER_FAIL ; +} + +////////////////////////////////////////////////////////////////////// +// Function: HDCP_ResumeAuthentication +// Parameter: N/A +// Return: N/A +// Remark: called by interrupt handler to restart Authentication and Encryption. +// Side-Effect: as Authentication and Encryption. +////////////////////////////////////////////////////////////////////// + +static void +HDCP_ResumeAuthentication() +{ + SetAVMute(TRUE) ; + if(HDCP_Authenticate() == ER_SUCCESS) + { + HDCP_EnableEncryption() ; + } + SetAVMute(FALSE) ; +} + + + +#endif // SUPPORT_HDCP + + +static void +ENABLE_NULL_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_ACP_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_ACP_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_ISRC1_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_ISRC1_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_ISRC2_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_ISRC2_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_AVI_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_AVI_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_AUD_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_AUD_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_SPD_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_SPD_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + + +static void +ENABLE_MPG_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_MPG_INFOFRM_CTRL,B_ENABLE_PKT|B_REPEAT_PKT); +} + +static void +DISABLE_NULL_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_NULL_CTRL,0); +} + + +static void +DISABLE_ACP_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_ACP_CTRL,0); +} + + +static void +DISABLE_ISRC1_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_ISRC1_CTRL,0); +} + + +static void +DISABLE_ISRC2_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_ISRC2_CTRL,0); +} + + +static void +DISABLE_AVI_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_AVI_INFOFRM_CTRL,0); +} + + +static void +DISABLE_AUD_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_AUD_INFOFRM_CTRL,0); +} + + +static void +DISABLE_SPD_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_SPD_INFOFRM_CTRL,0); +} + + +static void +DISABLE_MPG_INFOFRM_PKT() +{ + + HDMITX_WriteI2C_Byte(REG_TX_MPG_INFOFRM_CTRL,0); +} + + + +////////////////////////////////////////////////////////////////////// +// Function: SetAVIInfoFrame() +// Parameter: pAVIInfoFrame - the pointer to HDMI AVI Infoframe ucData +// Return: N/A +// Remark: Fill the AVI InfoFrame ucData,and count checksum,then fill into +// AVI InfoFrame registers. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +SetAVIInfoFrame(AVI_InfoFrame *pAVIInfoFrame) +{ + int i ; + byte ucData ; + + if(!pAVIInfoFrame) + { + return ER_FAIL ; + } + + Switch_HDMITX_Bank(1) ; + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB1,pAVIInfoFrame->pktbyte.AVI_DB[0]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB2,pAVIInfoFrame->pktbyte.AVI_DB[1]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB3,pAVIInfoFrame->pktbyte.AVI_DB[2]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB4,pAVIInfoFrame->pktbyte.AVI_DB[3]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB5,pAVIInfoFrame->pktbyte.AVI_DB[4]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB6,pAVIInfoFrame->pktbyte.AVI_DB[5]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB7,pAVIInfoFrame->pktbyte.AVI_DB[6]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB8,pAVIInfoFrame->pktbyte.AVI_DB[7]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB9,pAVIInfoFrame->pktbyte.AVI_DB[8]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB10,pAVIInfoFrame->pktbyte.AVI_DB[9]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB11,pAVIInfoFrame->pktbyte.AVI_DB[10]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB12,pAVIInfoFrame->pktbyte.AVI_DB[11]); + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_DB13,pAVIInfoFrame->pktbyte.AVI_DB[12]); + for(i = 0,ucData = 0; i < 13 ; i++) + { + ucData -= pAVIInfoFrame->pktbyte.AVI_DB[i] ; + } + ErrorF("SetAVIInfo(): ") ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB1)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB2)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB3)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB4)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB5)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB6)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB7)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB8)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB9)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB10)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB11)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB12)) ; + //ErrorF("%02X ",HDMITX_ReadI2C_Byte(REG_TX_AVIINFO_DB13)) ; + ErrorF("\n") ; + ucData -= 0x80+AVI_INFOFRAME_VER+AVI_INFOFRAME_TYPE+AVI_INFOFRAME_LEN ; + HDMITX_WriteI2C_Byte(REG_TX_AVIINFO_SUM,ucData); + + + Switch_HDMITX_Bank(0) ; + ENABLE_AVI_INFOFRM_PKT(); + return ER_SUCCESS ; +} + +////////////////////////////////////////////////////////////////////// +// Function: SetAudioInfoFrame() +// Parameter: pAudioInfoFrame - the pointer to HDMI Audio Infoframe ucData +// Return: N/A +// Remark: Fill the Audio InfoFrame ucData,and count checksum,then fill into +// Audio InfoFrame registers. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +SetAudioInfoFrame(Audio_InfoFrame *pAudioInfoFrame) +{ + int i ; + BYTE ucData ; + + if(!pAudioInfoFrame) + { + return ER_FAIL ; + } + + Switch_HDMITX_Bank(1) ; + HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_CC,pAudioInfoFrame->pktbyte.AUD_DB[0]); + HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_SF,pAudioInfoFrame->pktbyte.AUD_DB[1]); + HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_CA,pAudioInfoFrame->pktbyte.AUD_DB[3]); + HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_DM_LSV,pAudioInfoFrame->pktbyte.AUD_DB[4]) ; + + for(i = 0,ucData = 0 ; i< 5 ; i++) + { + ucData -= pAudioInfoFrame->pktbyte.AUD_DB[i] ; + } + ucData -= 0x80+AUDIO_INFOFRAME_VER+AUDIO_INFOFRAME_TYPE+AUDIO_INFOFRAME_LEN ; + + HDMITX_WriteI2C_Byte(REG_TX_PKT_AUDINFO_SUM,ucData) ; + + + Switch_HDMITX_Bank(0) ; + ENABLE_AUD_INFOFRM_PKT(); + return ER_SUCCESS ; +} + +////////////////////////////////////////////////////////////////////// +// Function: SetSPDInfoFrame() +// Parameter: pSPDInfoFrame - the pointer to HDMI SPD Infoframe ucData +// Return: N/A +// Remark: Fill the SPD InfoFrame ucData,and count checksum,then fill into +// SPD InfoFrame registers. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +SetSPDInfoFrame(SPD_InfoFrame *pSPDInfoFrame) +{ + int i ; + BYTE ucData ; + + if(!pSPDInfoFrame) + { + return ER_FAIL ; + } + + Switch_HDMITX_Bank(1) ; + for(i = 0,ucData = 0 ; i < 25 ; i++) + { + ucData -= pSPDInfoFrame->pktbyte.SPD_DB[i] ; + HDMITX_WriteI2C_Byte(REG_TX_PKT_SPDINFO_PB1+i,pSPDInfoFrame->pktbyte.SPD_DB[i]) ; + } + ucData -= 0x80+SPD_INFOFRAME_VER+SPD_INFOFRAME_TYPE+SPD_INFOFRAME_LEN ; + HDMITX_WriteI2C_Byte(REG_TX_PKT_SPDINFO_SUM,ucData) ; // checksum + Switch_HDMITX_Bank(0) ; + ENABLE_SPD_INFOFRM_PKT(); + return ER_SUCCESS ; +} + +////////////////////////////////////////////////////////////////////// +// Function: SetMPEGInfoFrame() +// Parameter: pMPEGInfoFrame - the pointer to HDMI MPEG Infoframe ucData +// Return: N/A +// Remark: Fill the MPEG InfoFrame ucData,and count checksum,then fill into +// MPEG InfoFrame registers. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +static SYS_STATUS +SetMPEGInfoFrame(MPEG_InfoFrame *pMPGInfoFrame) +{ + int i ; + BYTE ucData ; + + if(!pMPGInfoFrame) + { + return ER_FAIL ; + } + + Switch_HDMITX_Bank(1) ; + + HDMITX_WriteI2C_Byte(REG_TX_PKT_MPGINFO_FMT,pMPGInfoFrame->info.FieldRepeat|(pMPGInfoFrame->info.MpegFrame<<1)) ; + HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB0,pMPGInfoFrame->pktbyte.MPG_DB[0]) ; + HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB1,pMPGInfoFrame->pktbyte.MPG_DB[1]) ; + HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB2,pMPGInfoFrame->pktbyte.MPG_DB[2]) ; + HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_DB3,pMPGInfoFrame->pktbyte.MPG_DB[3]) ; + + for(ucData = 0,i = 0 ; i < 5 ; i++) + { + ucData -= pMPGInfoFrame->pktbyte.MPG_DB[i] ; + } + ucData -= 0x80+MPEG_INFOFRAME_VER+MPEG_INFOFRAME_TYPE+MPEG_INFOFRAME_LEN ; + + HDMITX_WriteI2C_Byte(REG_TX_PKG_MPGINFO_SUM,ucData) ; + + Switch_HDMITX_Bank(0) ; + ENABLE_SPD_INFOFRM_PKT() ; + + return ER_SUCCESS ; +} + + +////////////////////////////////////////////////////////////////////// +// Function: DumpCatHDMITXReg() +// Parameter: N/A +// Return: N/A +// Remark: Debug function,dumps the registers of CAT6611. +// Side-Effect: N/A +////////////////////////////////////////////////////////////////////// + +#ifdef HDMITX_REG_DEBUG +static void +DumpCatHDMITXReg() +{ + int i,j ; + BYTE reg ; + BYTE bank ; + BYTE ucData ; + + ErrorF(" ") ; + for(j = 0 ; j < 16 ; j++) + { + ErrorF(" %02X",j) ; + if((j == 3)||(j==7)||(j==11)) + { + ErrorF(" ") ; + } + } + ErrorF("\n -----------------------------------------------------\n") ; + + Switch_HDMITX_Bank(0) ; + + for(i = 0 ; i < 0x100 ; i+=16) + { + ErrorF("[%3X] ",i) ; + for(j = 0 ; j < 16 ; j++) + { + ucData = HDMITX_ReadI2C_Byte((BYTE)((i+j)&0xFF)) ; + ErrorF(" %02X",ucData) ; + if((j == 3)||(j==7)||(j==11)) + { + ErrorF(" -") ; + } + } + ErrorF("\n") ; + if((i % 0x40) == 0x30) + { + ErrorF(" -----------------------------------------------------\n") ; + } + } + + Switch_HDMITX_Bank(1) ; + for(i = 0x130; i < 0x1B0 ; i+=16) + { + ErrorF("[%3X] ",i) ; + for(j = 0 ; j < 16 ; j++) + { + ucData = HDMITX_ReadI2C_Byte((BYTE)((i+j)&0xFF)) ; + ErrorF(" %02X",ucData) ; + if((j == 3)||(j==7)||(j==11)) + { + ErrorF(" -") ; + } + } + ErrorF("\n") ; + if(i == 0x160) + { + ErrorF(" -----------------------------------------------------\n") ; + } + + } + Switch_HDMITX_Bank(0) ; +} +#endif diff --git a/software/sys_controller/it6613/it6613_drv.h b/software/sys_controller/it6613/it6613_drv.h new file mode 100644 index 0000000..f114a4d --- /dev/null +++ b/software/sys_controller/it6613/it6613_drv.h @@ -0,0 +1,844 @@ +#ifndef _IT6613_H_ +#define _IT6613_H_ + +//#define EXTERN_HDCPROM +///////////////////////////////////////// +// DDC Address +///////////////////////////////////////// +#define DDC_HDCP_ADDRESS 0x74 +#define DDC_EDID_ADDRESS 0xA0 +#define DDC_FIFO_MAXREQ 0x20 + +// I2C address + +#define _80MHz 80000000 +#define HDMI_TX_I2C_SLAVE_ADDR 0x98 // PCADR is ground, if PCADR=1, address=0x9A + +/////////////////////////////////////////////////////////////////////// +// Register offset +/////////////////////////////////////////////////////////////////////// + + +#define REG_TX_VENDOR_ID0 0x00 +#define REG_TX_VENDOR_ID1 0x01 +#define REG_TX_DEVICE_ID0 0x02 +#define REG_TX_DEVICE_ID1 0x03 + + #define O_DEVID 0 + #define M_DEVID 0xF + #define O_REVID 4 + #define M_REVID 0xF + +#define REG_TX_SW_RST 0x04 + #define B_ENTEST (1<<7) + #define B_REF_RST (1<<5) + #define B_AREF_RST (1<<4) + #define B_VID_RST (1<<3) + #define B_AUD_RST (1<<2) + #define B_HDMI_RST (1<<1) + #define B_HDCP_RST (1<<0) + +#define REG_TX_INT_CTRL 0x05 + #define B_INTPOL_ACTL 0 + #define B_INTPOL_ACTH (1<<7) + #define B_INT_PUSHPULL 0 + #define B_INT_OPENDRAIN (1<<6) + +#define REG_TX_INT_STAT1 0x06 + #define B_INT_AUD_OVERFLOW (1<<7) + #define B_INT_ROMACQ_NOACK (1<<6) + #define B_INT_RDDC_NOACK (1<<5) + #define B_INT_DDCFIFO_ERR (1<<4) + #define B_INT_ROMACQ_BUS_HANG (1<<3) + #define B_INT_DDC_BUS_HANG (1<<2) + #define B_INT_RX_SENSE (1<<1) + #define B_INT_HPD_PLUG (1<<0) + +#define REG_TX_INT_STAT2 0x07 + #define B_INT_HDCP_SYNC_DET_FAIL (1<<7) + #define B_INT_VID_UNSTABLE (1<<6) + #define B_INT_PKTACP (1<<5) + #define B_INT_PKTNULL (1<<4) + #define B_INT_PKTGENERAL (1<<3) + #define B_INT_KSVLIST_CHK (1<<2) + #define B_INT_AUTH_DONE (1<<1) + #define B_INT_AUTH_FAIL (1<<0) + +#define REG_TX_INT_STAT3 0x08 + #define B_INT_AUD_CTS (1<<6) + #define B_INT_VSYNC (1<<5) + #define B_INT_VIDSTABLE (1<<4) + #define B_INT_PKTMPG (1<<3) + #define B_INT_PKTSPD (1<<2) + #define B_INT_PKTAUD (1<<1) + #define B_INT_PKTAVI (1<<0) + +#define REG_TX_INT_MASK1 0x09 + #define B_AUDIO_OVFLW_MASK (1<<7) + #define B_DDC_NOACK_MASK (1<<5) + #define B_DDC_FIFO_ERR_MASK (1<<4) + #define B_DDC_BUS_HANG_MASK (1<<2) + #define B_RXSEN_MASK (1<<1) + #define B_HPD_MASK (1<<0) + +#define REG_TX_INT_MASK2 0x0A + #define B_PKT_AVI_MASK (1<<7) + #define B_PKT_VID_UNSTABLE_MASK (1<<6) + #define B_PKT_ACP_MASK (1<<5) + #define B_PKT_NULL_MASK (1<<4) + #define B_PKT_GEN_MASK (1<<3) + #define B_KSVLISTCHK_MASK (1<<2) + #define B_T_AUTH_DONE_MASK (1<<1) + #define B_AUTH_FAIL_MASK (1<<0) + +#define REG_TX_INT_MASK3 0x0B + #define B_HDCP_SYNC_DET_FAIL_MASK (1<<6) + #define B_AUDCTS_MASK (1<<5) + #define B_VSYNC_MASK (1<<4) + #define B_VIDSTABLE_MASK (1<<3) + #define B_PKT_MPG_MASK (1<<2) + #define B_PKT_SPD_MASK (1<<1) + #define B_PKT_AUD_MASK (1<<0) + + +#define REG_TX_INT_CLR0 0x0C + #define B_CLR_PKTACP (1<<7) + #define B_CLR_PKTNULL (1<<6) + #define B_CLR_PKTGENERAL (1<<5) + #define B_CLR_KSVLISTCHK (1<<4) + #define B_CLR_AUTH_DONE (1<<3) + #define B_CLR_AUTH_FAIL (1<<2) + #define B_CLR_RXSENSE (1<<1) + #define B_CLR_HPD (1<<0) + +#define REG_TX_INT_CLR1 0x0D + #define B_CLR_VSYNC (1<<7) + #define B_CLR_VIDSTABLE (1<<6) + #define B_CLR_PKTMPG (1<<5) + #define B_CLR_PKTSPD (1<<4) + #define B_CLR_PKTAUD (1<<3) + #define B_CLR_PKTAVI (1<<2) + #define B_CLR_HDCP_SYNC_DET_FAIL (1<<1) + #define B_CLR_VID_UNSTABLE (1<<0) + +#define REG_TX_SYS_STATUS 0x0E + // readonly + #define B_INT_ACTIVE (1<<7) + #define B_HPDETECT (1<<6) + #define B_RXSENDETECT (1<<5) + #define B_TXVIDSTABLE (1<<4) + // read/write + #define O_CTSINTSTEP 2 + #define M_CTSINTSTEP (3<<2) + #define B_CLR_AUD_CTS (1<<1) + #define B_INTACTDONE (1<<0) + +#define REG_TX_BANK_CTRL 0x0F + #define B_BANK0 0 + #define B_BANK1 1 + +// DDC + +#define REG_TX_DDC_MASTER_CTRL 0x10 + #define B_MASTERROM (1<<1) + #define B_MASTERDDC (0<<1) + #define B_MASTERHOST (1<<0) + #define B_MASTERHDCP (0<<0) + +#define REG_TX_DDC_HEADER 0x11 +#define REG_TX_DDC_REQOFF 0x12 +#define REG_TX_DDC_REQCOUNT 0x13 +#define REG_TX_DDC_EDIDSEG 0x14 +#define REG_TX_DDC_CMD 0x15 + #define CMD_DDC_SEQ_BURSTREAD 0 + #define CMD_LINK_CHKREAD 2 + #define CMD_EDID_READ 3 + #define CMD_FIFO_CLR 9 + #define CMD_GEN_SCLCLK 0xA + #define CMD_DDC_ABORT 0xF + +#define REG_TX_DDC_STATUS 0x16 + #define B_DDC_DONE (1<<7) + #define B_DDC_ACT (1<<6) + #define B_DDC_NOACK (1<<5) + #define B_DDC_WAITBUS (1<<4) + #define B_DDC_ARBILOSE (1<<3) + #define B_DDC_ERROR (B_DDC_NOACK|B_DDC_WAITBUS|B_DDC_ARBILOSE) + #define B_DDC_FIFOFULL (1<<2) + #define B_DDC_FIFOEMPTY (1<<1) + +#define REG_TX_DDC_READFIFO 0x17 +#define REG_TX_ROM_STARTADDR 0x18 +#define REG_TX_HDCP_HEADER 0x19 +#define REG_TX_ROM_HEADER 0x1A +#define REG_TX_BUSHOLD_T 0x1B +#define REG_TX_ROM_STAT 0x1C + #define B_ROM_DONE (1<<7) + #define B_ROM_ACTIVE (1<<6) + #define B_ROM_NOACK (1<<5) + #define B_ROM_WAITBUS (1<<4) + #define B_ROM_ARBILOSE (1<<3) + #define B_ROM_BUSHANG (1<<2) + +// HDCP +#define REG_TX_AN_GENERATE 0x1F + #define B_START_CIPHER_GEN 1 + #define B_STOP_CIPHER_GEN 0 + +#define REG_TX_HDCP_DESIRE 0x20 + #define B_ENABLE_HDPC11 (1<<1) + #define B_CPDESIRE (1<<0) + +#define REG_TX_AUTHFIRE 0x21 +#define REG_TX_LISTCTRL 0x22 + #define B_LISTFAIL (1<<1) + #define B_LISTDONE (1<<0) + +#define REG_TX_AKSV 0x23 +#define REG_TX_AKSV0 0x23 +#define REG_TX_AKSV1 0x24 +#define REG_TX_AKSV2 0x25 +#define REG_TX_AKSV3 0x26 +#define REG_TX_AKSV4 0x27 + +#define REG_TX_AN 0x28 +#define REG_TX_AN_GEN 0x30 +#define REG_TX_ARI 0x38 +#define REG_TX_ARI0 0x38 +#define REG_TX_ARI1 0x39 +#define REG_TX_APJ 0x3A + +#define REG_TX_BKSV 0x3B +#define REG_TX_BRI 0x40 +#define REG_TX_BRI0 0x40 +#define REG_TX_BRI1 0x41 +#define REG_TX_BPJ 0x42 +#define REG_TX_BCAP 0x43 + #define B_CAP_HDMI_REPEATER (1<<6) + #define B_CAP_KSV_FIFO_RDY (1<<5) + #define B_CAP_HDMI_FAST_MODE (1<<4) + #define B_CAP_HDCP_1p1 (1<<1) + #define B_CAP_FAST_REAUTH (1<<0) +#define REG_TX_BSTAT 0x44 +#define REG_TX_BSTAT0 0x44 +#define REG_TX_BSTAT1 0x45 + #define B_CAP_HDMI_MODE (1<<12) + #define B_CAP_DVI_MODE (0<<12) + #define B_MAX_CASCADE_EXCEEDED (1<<11) + #define M_REPEATER_DEPTH (0x7<<8) + #define O_REPEATER_DEPTH 8 + #define B_DOWNSTREAM_OVER (1<<7) + #define M_DOWNSTREAM_COUNT 0x7F + +#define REG_TX_AUTH_STAT 0x46 +#define B_T_AUTH_DONE (1<<7) +#define REG_TX_CLK_CTRL0 0x58 + #define O_OSCLK_SEL 5 + #define M_OSCLK_SEL 3 + #define B_AUTO_OVER_SAMPLING_CLOCK (1<<4) + #define O_EXT_MCLK_SEL 2 + #define M_EXT_MCLK_SEL (3<80000000 ) + { + level = PCLK_HIGH ; + } + else if(TMDSClock>20000000) + { + level = PCLK_MEDIUM ; + } + else + { + level = PCLK_LOW ; + } + + + + //BOOL EnableVideoOutput(VIDEOPCLKLEVEL level,BYTE inputColorMode,BYTE outputColorMode,BYTE bHDMI) ; + //EnableVideoOutput(level,bInputColorMode, bInputSignalType, bOutputColorMode,bHDMIMode) ; + EnableVideoOutput(level,bInputColorMode, bOutputColorMode,bHDMIMode) ; // richard modify + + if( bHDMIMode ) + { + OS_PRINTF("ConfigAVIInfoFrame, VIC=%d\n", VIC); + ConfigAVIInfoFrame(VIC, pixelrep) ; + + EnableHDCP(TRUE) ; + if( bAudioEnable ) + { + //BOOL EnableAudioOutput(ULONG VideoPixelClock,BYTE bAudioSampleFreq,BYTE ChannelNumber,BYTE bAudSWL,BYTE bSPDIF) + //EnableAudioOutput(TMDSClock,48000, 2, FALSE); + bool bSPDIF = FALSE; + EnableAudioOutput(TMDSClock,AUDFS_48KHz, 2, 16, bSPDIF); // richard modify + ConfigAudioInfoFrm() ; + } + } + SetAVMute(FALSE) ; + bChangeMode = FALSE ; +} + + + +void +HDMITX_ChangeDisplayOption(HDMI_Video_Type OutputVideoTiming, HDMI_OutputColorMode OutputColorMode) +{ + //HDMI_Video_Type t=HDMI_480i60_16x9; + switch(OutputVideoTiming) + { + case HDMI_640x480p60: + VIC = 1 ; + VideoPixelClock = 25000000 ; + pixelrep = 0 ; + aspec = HDMI_4x3 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_480p60: + VIC = 2 ; + VideoPixelClock = 27000000 ; + pixelrep = 0 ; + aspec = HDMI_4x3 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_480p60_16x9: + VIC = 3 ; + VideoPixelClock = 27000000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_720p60: + VIC = 4 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_1080i60: + VIC = 5 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_480i60: + VIC = 6 ; + VideoPixelClock = 13500000 ; + pixelrep = 1 ; + aspec = HDMI_4x3 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_480i60_16x9: + VIC = 7 ; + VideoPixelClock = 13500000 ; + pixelrep = 1 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_1080p60: + VIC = 16 ; + VideoPixelClock = 148500000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_576p50: + VIC = 17 ; + VideoPixelClock = 27000000 ; + pixelrep = 0 ; + aspec = HDMI_4x3 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_576p50_16x9: + VIC = 18 ; + VideoPixelClock = 27000000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_720p50: + VIC = 19 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_1080i50: + VIC = 20 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_576i50: + VIC = 21 ; + VideoPixelClock = 13500000 ; + pixelrep = 1 ; + aspec = HDMI_4x3 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_576i50_16x9: + VIC = 22 ; + VideoPixelClock = 13500000 ; + pixelrep = 1 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU601 ; + break ; + case HDMI_1080p50: + VIC = 31 ; + VideoPixelClock = 148500000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_1080p24: + VIC = 32 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_1080p25: + VIC = 33 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_1080p30: + VIC = 34 ; + VideoPixelClock = 74250000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU709 ; + break ; + case HDMI_1080i120:// richard add + VIC = 46 ; + VideoPixelClock = 148500000 ; + pixelrep = 0 ; + aspec = HDMI_16x9 ; + Colorimetry = HDMI_ITU601 ; + break ; + + + default: + VIC = 0; // richard add + bChangeMode = FALSE ; + return ; + } + + switch(OutputColorMode) + { + case HDMI_YUV444: + bOutputColorMode = F_MODE_YUV444 ; + break ; + case HDMI_YUV422: + bOutputColorMode = F_MODE_YUV422 ; + break ; + case HDMI_RGB444: + default: + bOutputColorMode = F_MODE_RGB444 ; + break ; + } + + if( Colorimetry == HDMI_ITU709 ) + { + bInputColorMode |= F_VIDMODE_ITU709 ; + } + else + { + bInputColorMode &= ~F_VIDMODE_ITU709 ; + } + + if( Colorimetry != HDMI_640x480p60) + { + bInputColorMode |= F_VIDMODE_16_235 ; + } + else + { + bInputColorMode &= ~F_VIDMODE_16_235 ; + } + + bChangeMode = TRUE ; +} + + +void +ConfigAVIInfoFrame(BYTE VIC, BYTE pixelrep) +{ +// AVI_InfoFrame AviInfo; + + AviInfo.pktbyte.AVI_HB[0] = AVI_INFOFRAME_TYPE|0x80 ; + AviInfo.pktbyte.AVI_HB[1] = AVI_INFOFRAME_VER ; + AviInfo.pktbyte.AVI_HB[2] = AVI_INFOFRAME_LEN ; + + switch(bOutputColorMode) + { + case F_MODE_YUV444: + // AviInfo.info.ColorMode = 2 ; + AviInfo.pktbyte.AVI_DB[0] = (2<<5)|(1<<4) ; + break ; + case F_MODE_YUV422: + // AviInfo.info.ColorMode = 1 ; + AviInfo.pktbyte.AVI_DB[0] = (1<<5)|(1<<4) ; + break ; + case F_MODE_RGB444: + default: + // AviInfo.info.ColorMode = 0 ; + AviInfo.pktbyte.AVI_DB[0] = (0<<5)|(1<<4) ; + break ; + } + AviInfo.pktbyte.AVI_DB[1] = 8 ; + AviInfo.pktbyte.AVI_DB[1] |= (aspec != HDMI_16x9)?(1<<4):(2<<4) ; // 4:3 or 16:9 + AviInfo.pktbyte.AVI_DB[1] |= (Colorimetry != HDMI_ITU709)?(1<<6):(2<<6) ; // 4:3 or 16:9 + AviInfo.pktbyte.AVI_DB[2] = 0 ; + AviInfo.pktbyte.AVI_DB[3] = VIC ; + AviInfo.pktbyte.AVI_DB[4] = pixelrep & 3 ; + AviInfo.pktbyte.AVI_DB[5] = 0 ; + AviInfo.pktbyte.AVI_DB[6] = 0 ; + AviInfo.pktbyte.AVI_DB[7] = 0 ; + AviInfo.pktbyte.AVI_DB[8] = 0 ; + AviInfo.pktbyte.AVI_DB[9] = 0 ; + AviInfo.pktbyte.AVI_DB[10] = 0 ; + AviInfo.pktbyte.AVI_DB[11] = 0 ; + AviInfo.pktbyte.AVI_DB[12] = 0 ; + + EnableAVIInfoFrame(TRUE, (unsigned char *)&AviInfo) ; +} + + + +//////////////////////////////////////////////////////////////////////////////// +// Function: ConfigAudioInfoFrm +// Parameter: NumChannel, number from 1 to 8 +// Return: ER_SUCCESS for successfull. +// Remark: Evaluate. The speakerplacement is only for reference. +// For production, the caller of SetAudioInfoFrame should program +// Speaker placement by actual status. +// Side-Effect: +//////////////////////////////////////////////////////////////////////////////// + +void +ConfigAudioInfoFrm() +{ + int i ; + ErrorF("ConfigAudioInfoFrm(%d)\n",2) ; + + AudioInfo.pktbyte.AUD_HB[0] = AUDIO_INFOFRAME_TYPE ; + AudioInfo.pktbyte.AUD_HB[1] = 1 ; + AudioInfo.pktbyte.AUD_HB[2] = AUDIO_INFOFRAME_LEN ; + AudioInfo.pktbyte.AUD_DB[0] = 1 ; + for( i = 1 ;i < AUDIO_INFOFRAME_LEN ; i++ ) + { + AudioInfo.pktbyte.AUD_DB[i] = 0 ; + } + EnableAudioInfoFrame(TRUE, (unsigned char *)&AudioInfo) ; +} + + + +///////////////////////////////////////////////////////////////////// +// ParseEDID() +// Check EDID check sum and EDID 1.3 extended segment. +///////////////////////////////////////////////////////////////////// + +BOOL +ParseEDID() +{ + // collect the EDID ucdata of segment 0 + BYTE CheckSum ; + BYTE BlockCount ; + BOOL err ; + BOOL bValidCEA = FALSE ; + int i ; + + RxCapability.ValidCEA = FALSE ; + + // richard GetEDIDData(0, EDID_Buf); + if (!GetEDIDData(0, EDID_Buf)) + return FALSE; + + + for( i = 0, CheckSum = 0 ; i < 128 ; i++ ) + { + CheckSum += EDID_Buf[i] ; CheckSum &= 0xFF ; + } + + //Eep_Write(0x80, 0x80, EDID_Buf) ; + if( CheckSum != 0 ) // 128-byte EDID sum shall equal zero + { + return FALSE ; + } + + // check EDID Header + if( EDID_Buf[0] != 0x00 || + EDID_Buf[1] != 0xFF || + EDID_Buf[2] != 0xFF || + EDID_Buf[3] != 0xFF || + EDID_Buf[4] != 0xFF || + EDID_Buf[5] != 0xFF || + EDID_Buf[6] != 0xFF || + EDID_Buf[7] != 0x00) + { + return FALSE ; + } + + + BlockCount = EDID_Buf[0x7E] ; // Extention Flash: Number of 128-byte EDID extesion blocks to follow + + if( BlockCount == 0 ) + { + return TRUE ; // do nothing. + } + else if ( BlockCount > 4 ) + { + BlockCount = 4 ; + } + + // read all segment for test + for( i = 1 ; i <= BlockCount ; i++ ) + { + err = GetEDIDData(i, EDID_Buf) ; + + if( err ) + { + if( !bValidCEA && EDID_Buf[0] == 0x2 && EDID_Buf[1] == 0x3 ) //EDID_Buf[0] == 0x2 ==> Additional timing data type 2 + { + // richard change + //err = ParseCEAEDID(EDID_Buf) ; + err = ParseCEAEDID(EDID_Buf, &RxCapability); + if( err ) + { + + if(RxCapability.IEEEOUI==0x0c03) + { + RxCapability.ValidHDMI = TRUE ; + bValidCEA = TRUE ; + } + else + { + RxCapability.ValidHDMI = FALSE ; + } + + } + } + } + } + + return err?FALSE:TRUE ; // richard modify + +} + +/* richard: use the one defined edid.c +static BOOL +ParseCEAEDID(BYTE *pCEAEDID) +{ + BYTE offset,End ; + BYTE count ; + BYTE tag ; + int i ; + +// richard if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) return ER_SUCCESS ; // not a CEA BLOCK. + if( pCEAEDID[0] != 0x02 || pCEAEDID[1] != 0x03 ) // not a CEA BLOCK. + return FALSE; + End = pCEAEDID[2] ; // CEA description. + RxCapability.VideoMode = pCEAEDID[3] ; + + RxCapability.VDOModeCount = 0 ; + RxCapability.idxNativeVDOMode = 0xff ; + + for( offset = 4 ; offset < End ; ) + { + tag = pCEAEDID[offset] >> 5 ; + count = pCEAEDID[offset] & 0x1f ; + switch( tag ) + { + case 0x01: // Audio Data Block ; + RxCapability.AUDDesCount = count/3 ; + offset++ ; + for( i = 0 ; i < RxCapability.AUDDesCount ; i++ ) + { + RxCapability.AUDDes[i].uc[0] = pCEAEDID[offset++] ; + RxCapability.AUDDes[i].uc[1] = pCEAEDID[offset++] ; + RxCapability.AUDDes[i].uc[2] = pCEAEDID[offset++] ; + } + + break ; + + case 0x02: // Video Data Block ; + //RxCapability.VDOModeCount = 0 ; + offset ++ ; + for( i = 0,RxCapability.idxNativeVDOMode = 0xff ; i < count ; i++, offset++ ) + { + BYTE VIC ; + VIC = pCEAEDID[offset] & (~0x80) ; + // if( FindModeTableEntryByVIC(VIC) != -1 ) + { + RxCapability.VDOMode[RxCapability.VDOModeCount] = VIC ; + if( pCEAEDID[offset] & 0x80 ) + { + RxCapability.idxNativeVDOMode = (BYTE)RxCapability.VDOModeCount ; + iVideoModeSelect = RxCapability.VDOModeCount ; + } + + RxCapability.VDOModeCount++ ; + } + } + break ; + + case 0x03: // Vendor Specific Data Block ; + offset ++ ; + RxCapability.IEEEOUI = (ULONG)pCEAEDID[offset+2] ; + RxCapability.IEEEOUI <<= 8 ; + RxCapability.IEEEOUI += (ULONG)pCEAEDID[offset+1] ; + RxCapability.IEEEOUI <<= 8 ; + RxCapability.IEEEOUI += (ULONG)pCEAEDID[offset] ; + offset += count ; // ignore the remaind. + + break ; + + case 0x04: // Speaker Data Block ; + offset ++ ; + RxCapability.SpeakerAllocBlk.uc[0] = pCEAEDID[offset] ; + RxCapability.SpeakerAllocBlk.uc[1] = pCEAEDID[offset+1] ; + RxCapability.SpeakerAllocBlk.uc[2] = pCEAEDID[offset+2] ; + offset += 3 ; + break ; + case 0x05: // VESA Data Block ; + offset += count+1 ; + break ; + case 0x07: // Extended Data Block ; + offset += count+1 ; //ignore + break ; + default: + offset += count+1 ; // ignore + } + } + RxCapability.ValidCEA = TRUE ; + return TRUE ; +} +*/ + diff --git a/software/sys_controller/it6613/it6613_sys.h b/software/sys_controller/it6613/it6613_sys.h new file mode 100644 index 0000000..72cac78 --- /dev/null +++ b/software/sys_controller/it6613/it6613_sys.h @@ -0,0 +1,63 @@ +#ifndef _CAT6611_SYS_H_ +#define _CAT6611_SYS_H_ +//////////////////////////////////////////////////////////////////////////////// +// Internal Data Type +//////////////////////////////////////////////////////////////////////////////// + +typedef enum tagHDMI_Video_Type { + HDMI_Unkown = 0 , + HDMI_640x480p60 = 1 , + HDMI_480p60, + HDMI_480p60_16x9, + HDMI_720p60, + HDMI_1080i60, + HDMI_480i60, + HDMI_480i60_16x9, + HDMI_1080p60 = 16, + HDMI_576p50, + HDMI_576p50_16x9, + HDMI_720p50 = 19, + HDMI_1080i50, + HDMI_576i50, + HDMI_576i50_16x9, + HDMI_1080p50 = 31, + HDMI_1080p24, + HDMI_1080p25, + HDMI_1080p30, + HDMI_1080i120 = 46, // richard add +} HDMI_Video_Type ; + +typedef enum tagHDMI_Aspec { + HDMI_4x3 , + HDMI_16x9 +} HDMI_Aspec; + +typedef enum tagHDMI_OutputColorMode { + HDMI_RGB444, + HDMI_YUV444, + HDMI_YUV422 +} HDMI_OutputColorMode ; + +typedef enum tagHDMI_Colorimetry { + HDMI_ITU601, + HDMI_ITU709 +} HDMI_Colorimetry ; + +/////////////////////////////////////////////////////////////////////// +// Output Mode Type +/////////////////////////////////////////////////////////////////////// + +#define RES_ASPEC_4x3 0 +#define RES_ASPEC_16x9 1 +#define F_MODE_REPT_NO 0 +#define F_MODE_REPT_TWICE 1 +#define F_MODE_REPT_QUATRO 3 +#define F_MODE_CSC_ITU601 0 +#define F_MODE_CSC_ITU709 1 + +void HDMITX_ChangeDisplayOption(HDMI_Video_Type VideoMode, HDMI_OutputColorMode OutputColorMode); +void HDMITX_SetOutput(); + + + +#endif // _CAT6611_SYS_H_ diff --git a/software/sys_controller/it6613/typedef.h b/software/sys_controller/it6613/typedef.h new file mode 100644 index 0000000..2f8ff4f --- /dev/null +++ b/software/sys_controller/it6613/typedef.h @@ -0,0 +1,329 @@ +#ifndef _TYPEDEF_H_ +#define _TYPEDEF_H_ + +////////////////////////////////////////////////// +// data type +////////////////////////////////////////////////// +#ifdef _MCU_ +typedef bit BOOL ; +#define _CODE //richard code +#define _IDATA //richard idata +#define _XDATA //richard xdata +#else +typedef int BOOL ; +#define _CODE +#define _IDATA +#define _XDATA +#endif // _MCU_ + + + +typedef char CHAR,*PCHAR ; +typedef unsigned char uchar,*puchar ; +typedef unsigned char UCHAR,*PUCHAR ; +typedef unsigned char byte,*pbyte ; +typedef unsigned char BYTE,*PBYTE ; + +typedef short SHORT,*PSHORT ; +typedef unsigned short ushort,*pushort ; +typedef unsigned short USHORT,*PUSHORT ; +typedef unsigned short word,*pword ; +typedef unsigned short WORD,*PWORD ; + +typedef long LONG,*PLONG ; +typedef unsigned long ulong,*pulong ; +typedef unsigned long ULONG,*PULONG ; +typedef unsigned long dword,*pdword ; +typedef unsigned long DWORD,*PDWORD ; + +#define FALSE 0 +#define TRUE 1 + +#define SUCCESS 0 +#define FAIL -1 + +#define ON 1 +#define OFF 0 + +typedef enum _SYS_STATUS { + ER_SUCCESS = 0, + ER_FAIL, + ER_RESERVED +} SYS_STATUS ; + +#define abs(x) (((x)>=0)?(x):(-(x))) + + +typedef enum _Video_State_Type { + VSTATE_PwrOff = 0, + VSTATE_SyncWait , + VSTATE_SWReset, + VSTATE_SyncChecking, + VSTATE_HDCPSet, + VSTATE_HDCP_Reset, + VSTATE_ModeDetecting, + VSTATE_VideoOn, + VSTATE_Reserved +} Video_State_Type ; + + +typedef enum _Audio_State_Type { + ASTATE_AudioOff = 0, + ASTATE_RequestAudio , + ASTATE_ResetAudio, + ASTATE_WaitForReady, + ASTATE_AudioOn , + ASTATE_Reserved +} Audio_State_Type ; + +typedef enum _TXVideo_State_Type { + TXVSTATE_Unplug = 0, + TXVSTATE_HPD, + TXVSTATE_WaitForMode, + TXVSTATE_WaitForVStable, + TXVSTATE_VideoInit, + TXVSTATE_VideoSetup, + TXVSTATE_VideoOn, + TXVSTATE_Reserved +} TXVideo_State_Type ; + + +typedef enum _TXAudio_State_Type { + TXASTATE_AudioOff = 0, + TXASTATE_AudioPrepare, + TXASTATE_AudioOn, + TXASTATE_AudioFIFOFail, + TXASTATE_Reserved +} TXAudio_State_Type ; + + + + +typedef enum { + PCLK_LOW = 0 , + PCLK_MEDIUM, + PCLK_HIGH +} VIDEOPCLKLEVEL ; + +/////////////////////////////////////////////////////////////////////// +// Video Data Type +/////////////////////////////////////////////////////////////////////// +#define F_MODE_RGB24 0 +#define F_MODE_RGB444 0 +#define F_MODE_YUV422 1 +#define F_MODE_YUV444 2 +#define F_MODE_CLRMOD_MASK 3 + + +#define F_MODE_INTERLACE 1 + +#define F_MODE_ITU709 (1<<4) +#define F_MODE_ITU601 0 + +#define F_MODE_0_255 0 +#define F_MODE_16_235 (1<<5) + +#define F_MODE_EN_UDFILT (1<<6) // output mode only,and loaded from EEPROM +#define F_MODE_EN_DITHER (1<<7) // output mode only,and loaded from EEPROM + +#define F_VIDMODE_ITU709 F_MODE_ITU709 // richard add +#define F_VIDMODE_16_235 F_MODE_16_235 // richard add + + +typedef union _VideoFormatCode +{ + struct _VFC + { + BYTE colorfmt:2 ; + BYTE interlace:1 ; + BYTE Colorimetry:1 ; + BYTE Quantization:1 ; + BYTE UpDownFilter:1 ; + BYTE Dither:1 ; + } VFCCode ; + unsigned char VFCByte ; +} VideoFormatCode ; + +#define T_MODE_CCIR656 (1<<0) +#define T_MODE_SYNCEMB (1<<1) +#define T_MODE_INDDR (1<<2) +#define T_MODE_PCLKDIV2 (1<<3) +#define T_MODE_DEGEN (1<<4) +#define T_MODE_SYNCGEN (1<<5) +////////////////////////////////////////////////////////////////// +// Audio relate definition and macro. +////////////////////////////////////////////////////////////////// + +// for sample clock +#define AUDFS_22p05KHz 4 +#define AUDFS_44p1KHz 0 +#define AUDFS_88p2KHz 8 +#define AUDFS_176p4KHz 12 + +#define AUDFS_24KHz 6 +#define AUDFS_48KHz 2 +#define AUDFS_96KHz 10 +#define AUDFS_192KHz 14 + +#define AUDFS_32KHz 3 +#define AUDFS_OTHER 1 + +// Audio Enable +#define ENABLE_SPDIF (1<<4) +#define ENABLE_I2S_SRC3 (1<<3) +#define ENABLE_I2S_SRC2 (1<<2) +#define ENABLE_I2S_SRC1 (1<<1) +#define ENABLE_I2S_SRC0 (1<<0) + +#define AUD_SWL_NOINDICATE 0x0 +#define AUD_SWL_16 0x2 +#define AUD_SWL_17 0xC +#define AUD_SWL_18 0x4 +#define AUD_SWL_20 0xA // for maximum 20 bit +#define AUD_SWL_21 0xD +#define AUD_SWL_22 0x5 +#define AUD_SWL_23 0x9 +#define AUD_SWL_24 0xB + + +///////////////////////////////////////////////////////////////////// +// Packet and Info Frame definition and datastructure. +///////////////////////////////////////////////////////////////////// + +#define VENDORSPEC_INFOFRAME_TYPE 0x01 +#define AVI_INFOFRAME_TYPE 0x02 +#define SPD_INFOFRAME_TYPE 0x03 +#define AUDIO_INFOFRAME_TYPE 0x04 +#define MPEG_INFOFRAME_TYPE 0x05 + +#define VENDORSPEC_INFOFRAME_VER 0x01 +#define AVI_INFOFRAME_VER 0x02 +#define SPD_INFOFRAME_VER 0x01 +#define AUDIO_INFOFRAME_VER 0x01 +#define MPEG_INFOFRAME_VER 0x01 + +#define VENDORSPEC_INFOFRAME_LEN 8 +#define AVI_INFOFRAME_LEN 13 +#define SPD_INFOFRAME_LEN 25 +#define AUDIO_INFOFRAME_LEN 10 +#define MPEG_INFOFRAME_LEN 10 + +#define ACP_PKT_LEN 9 +#define ISRC1_PKT_LEN 16 +#define ISRC2_PKT_LEN 16 + +typedef union _AVI_InfoFrame +{ + struct { + BYTE Type ; + BYTE Ver ; + BYTE Len ; + + BYTE Scan:2 ; + BYTE BarInfo:2 ; + BYTE ActiveFmtInfoPresent:1 ; + BYTE ColorMode:2 ; + BYTE FU1:1 ; + + BYTE ActiveFormatAspectRatio:4 ; + BYTE PictureAspectRatio:2 ; + BYTE Colorimetry:2 ; + + BYTE Scaling:2 ; + BYTE FU2:6 ; + + BYTE VIC:7 ; + BYTE FU3:1 ; + + BYTE PixelRepetition:4 ; + BYTE FU4:4 ; + + SHORT Ln_End_Top ; + SHORT Ln_Start_Bottom ; + SHORT Pix_End_Left ; + SHORT Pix_Start_Right ; + } info ; + struct { + BYTE AVI_HB[3] ; + BYTE AVI_DB[AVI_INFOFRAME_LEN] ; + } pktbyte ; +} AVI_InfoFrame ; + +typedef union _Audio_InfoFrame { + + struct { + BYTE Type ; + BYTE Ver ; + BYTE Len ; + + BYTE AudioChannelCount:3 ; + BYTE RSVD1:1 ; + BYTE AudioCodingType:4 ; + + BYTE SampleSize:2 ; + BYTE SampleFreq:3 ; + BYTE Rsvd2:3 ; + + BYTE FmtCoding ; + + BYTE SpeakerPlacement ; + + BYTE Rsvd3:3 ; + BYTE LevelShiftValue:4 ; + BYTE DM_INH:1 ; + } info ; + + struct { + BYTE AUD_HB[3] ; + BYTE AUD_DB[AUDIO_INFOFRAME_LEN] ; + } pktbyte ; + +} Audio_InfoFrame ; + +typedef union _MPEG_InfoFrame { + struct { + BYTE Type ; + BYTE Ver ; + BYTE Len ; + + ULONG MpegBitRate ; + + BYTE MpegFrame:2 ; + BYTE Rvsd1:2 ; + BYTE FieldRepeat:1 ; + BYTE Rvsd2:3 ; + } info ; + struct { + BYTE MPG_HB[3] ; + BYTE MPG_DB[MPEG_INFOFRAME_LEN] ; + } pktbyte ; +} MPEG_InfoFrame ; + +// Source Product Description +typedef union _SPD_InfoFrame { + struct { + BYTE Type ; + BYTE Ver ; + BYTE Len ; + + char VN[8] ; // vendor name character in 7bit ascii characters + char PD[16] ; // product description character in 7bit ascii characters + BYTE SourceDeviceInfomation ; + } info ; + struct { + BYTE SPD_HB[3] ; + BYTE SPD_DB[SPD_INFOFRAME_LEN] ; + } pktbyte ; +} SPD_InfoFrame ; + +/////////////////////////////////////////////////////////////////////////// +// Using for interface. +/////////////////////////////////////////////////////////////////////////// +struct VideoTiming { + ULONG VideoPixelClock ; + BYTE VIC ; + BYTE pixelrep ; + BYTE outputVideoMode ; +} ; + +#endif // _TYPEDEF_H_ diff --git a/software/sys_controller/mem_init/epcq_controller_0.hex b/software/sys_controller/mem_init/epcq_controller_0.hex new file mode 100644 index 0000000..7c166a1 --- /dev/null +++ b/software/sys_controller/mem_init/epcq_controller_0.hex @@ -0,0 +1 @@ +:00000001FF diff --git a/software/sys_controller/mem_init/meminit.qip b/software/sys_controller/mem_init/meminit.qip new file mode 100644 index 0000000..7589c13 --- /dev/null +++ b/software/sys_controller/mem_init/meminit.qip @@ -0,0 +1 @@ +set_global_assignment -name SEARCH_PATH $::quartus(qip_path) diff --git a/software/sys_controller/mem_init/meminit.spd b/software/sys_controller/mem_init/meminit.spd new file mode 100644 index 0000000..965f43f --- /dev/null +++ b/software/sys_controller/mem_init/meminit.spd @@ -0,0 +1,6 @@ + + + + + + diff --git a/software/sys_controller/mem_init/sys_onchip_memory2_0.hex b/software/sys_controller/mem_init/sys_onchip_memory2_0.hex new file mode 100644 index 0000000..e22a92b --- /dev/null +++ b/software/sys_controller/mem_init/sys_onchip_memory2_0.hex @@ -0,0 +1,1154 @@ +:020000020000FC +:2000000000402074084008140800683A0000000000000000000000000000000000000000FE +:2000080006C02074DEE4001406802074D6B9A81400802074109ACE1400C0207418DB0A143E +:2000100010C00326100000151080010410FFFD3608147B4008148AC0003FFF060080207446 +:200018001098FC0410C03217D0A128151800042610803517108040180085C83AF800283A72 +:2000200000BFFFC4F800283ADEFFFD042005883AD1212817DC4001152823883A880F883A56 +:20002800100B883ADC000015DFC002153021883A0814FB0010000B1E800D883A8463883AD9 +:2000300034400626308000031005C2721005D63A3180004430BFFFC5003FF9060005883A42 +:200038000000010600BFFFC4DFC00217DC400117DC000017DEC00304F800283ADEFFFA0466 +:20004000DC800315DC400215DC000115DFC00515DCC0041530803FCC2023883A2825883ACA +:200048003021883A100003268805883A8C89883A00001706D1212817300A923A0814CB40AB +:200050001027883A103FF8260100207401402074211AEA0429565804018004440814054092 +:200058000100207401802074211AEA040140044431965B04980F883A0813F58000802074F9 +:20006000109AF5C41000000500FFCE0400001D061100062610C000031807C2721807D63A82 +:200068001080004410FFFFC5003FF906800AD23AD1212817800C923A280A943ADC80001503 +:20007000880F883A0814D4800007883A10000D260100207401402074211AEA0429565E0427 +:2000780001800444081405400100207401402074211AF5C4295661040180044408140540D2 +:2000800000FFCDC41805883ADFC00517DCC00417DC800317DC400217DC000117DEC0060438 +:20008800F800283ADEFFF904DD400515DD000415DCC00315DC800215DC000015DFC0061525 +:20009000DC4001152825883A3029883A3827883A0021883A0007883A0540400484800F2E5D +:200098009423C83AAC40012E044040048009883A880B883A980D883A081008801000141E03 +:2000A000800D003A9809883A880B883A081517001007883A84004004003FF0060005883AF0 +:2000A8001D000C260100207401802074211AEA0401400444319663040813F58000802074BB +:2000B000109AF5C41000000500BFCD440000010600BFCD84DFC00617DD400517DD000417E4 +:2000B800DCC00317DC800217DC400117DC000017DEC00704F800283ADEFFFD04DFC002153F +:2000C000DC400115DC00001520807FCC1000031E008080042821883A11400B2E01002074B3 +:2000C80001802074211AEA0401400444319668040813F58000802074109AF5C41000000502 +:2000D00000BFFFC400001C062008D27A000B883A3023883A0814A8C010803FCC0007883A2E +:2000D80010000B1E0100207401802074211AEA040140044431966D040813F5800080207497 +:2000E000109AF5C41000000500BFFF8400000A061C00082ED0A1271710800A171885883A25 +:2000E8001100003788C5883A1100001518C00104003FF7060005883ADFC00217DC400117AF +:2000F000DC000017DEC00304F800283ADEFFFE04DC0000152021883A0100207421167104EA +:2000F800DFC00115081495C0D0A1271510000A2608149B8010803FCC100007260009883AFB +:2001000001408004800D883ADFC00117DC000017DEC0020408102F8101002074018020740B +:20010800211AEA040140044431967C040813F58000802074109AF5C41000000500800044FE +:20011000DFC00117DC000017DEC00204F800283ADEFFFB04DC4002152023883ADC00011521 +:200118002809883A2821883A01800104880B883ADFC00415DC80031508140540014020748C +:200120008009883A2956800401800104081401001025883A10000B260100207401802074EC +:20012800211AEA0401400444319682040813F58000802074109AF5C41000000504800044D4 +:200130000000430688800103810001848940018480800105888001430180020480800145E7 +:2001380008140540D809883A8000034589400384018001040813F300D88000171005C2327F +:2001400080800415D809883A89400484018001040813F300D88000171005C232808005156C +:20014800D809883A89400584018001040813F300D88000171005C23280800615D809883AD8 +:2001500089407F04018001040813F300D88000171005C232814004178080071500C0788483 +:2001580028BFF98418800B2E0100207401802074211AEA0401400444319686040813F58015 +:2001600000802074109AF5C41000000504BFFFC400000F068809883A01800044081517000C +:2001680080C0071710C00A260100207401802074211AEA040140044431968A040813F580D8 +:2001700000802074109AF5C41000000504BFFF849005883ADFC00417DC800317DC400217E1 +:20017800DC000117DEC00504F800283ADEFFF804DD800615DD400515DD000415DCC0031540 +:20018000DC800215DC000015DFC00715DC400115202B883A2825883A3029883A3827883AB6 +:200188000021883A0007883A0580800484800F2E9423C83AB440012E044080048549883A2D +:20019000880B883A980D883A08102F801000141E800D003A9809883A880B883A08151700D7 +:200198001007883A84008004003FF0060005883A1D000C260100207401802074211AEA0448 +:2001A0000140044431968E040813F58000802074109AF5C41000000500BFFF440000010638 +:2001A80000BFFF84DFC00717DD800617DD400517DD000417DCC00317DC800217DC4001172E +:2001B000DC000017DEC00804F800283ADEFF6D04D9000304DC008B15DFC09215DD80911545 +:2001B800DD409015DD008F15DCC08E15DC808D15DC408C1508103CC01021883A10009D1E18 +:2001C000D9000304D9408304081045001021883A1000981E0100207401802074211AEA04B6 +:2001C80001400444319694040813F580D9C08817010020740180207431969804211AF5C466 +:2001D000014004440813F5800100207401402074211AEA04295AF5C40812F600D94088175F +:2001D800D980891701008004D9C0030408105EC01021883A10007F1ED8808487D9C0840390 +:2001E000D8C0844310000326008020741096930400000206008020741096CD04D880011515 +:2001E80001002074D880848401802074D8C00015211AEA040140044431969B04D8800215B9 +:2001F0000813F5800100207401402074211AF5C42956AD04018004440813F3000100207465 +:2001F80001402074211AEA04295AF5C4044020B4040020740812F6008C4520048418A004B8 +:200200008880003780C0000B10BFFFCC10C0052680C0008B10C06B260109C40408148EC057 +:20020800003FF70608133F4000C020B418C524041880003710800114188000350109C40454 +:2002100008148EC00100207401402074211AEA0429569E04018004440814054004C000C4FE +:200218000100207401402074211AF5C42956A10401800444081405400100207401402074B0 +:20022000211AEA04295AF5C40812F6000021883A0580800405004004DC40881784401C2E4B +:200228008C23C83AB440012E0440800485408004A809883A880B883AD980030408102F80E2 +:200230001000421E8025D23A880B883AA440012E01404004D9000304900D883A08100FC07A +:200238001021883A1000241EA4400236A821883A003FE906D9004304897FC004918000444B +:2002400008100FC01021883A103FF82600001A060100207401402074211AEA042956A5047C +:200248000180044408140540010020740140207401800444211AF5C42956A10408140540C0 +:200250000100207401402074211AEA04295AF5C40812F600D9408817D98089170009883A33 +:20025800D9C00304081022401021883A1000021E0000180604C000C4010020740140207439 +:20026000211AEA04295AF5C40812F600010003F42110900408148EC000BFCE4480800F0EF4 +:2002680004C00E0E0100207401802074211AEA04014004443196A9040813F5809CFFFFC4D8 +:20027000003FA706008000440000050600BFCE04000003060005883A0000010600BFFFC4C9 +:20027800DFC09217DD809117DD409017DD008F17DCC08E17DC808D17DC408C17DC008B1754 +:20028000DEC09304F800283A009114B4DEFFBF041094D544D88000150080107410951044AF +:20028800D8800115D0A12643D809883A014002C4D8800205D0A0000301840004DFC0401515 +:20029000D880024500800084D880028508100FC01000022600BFFFC4000020060140207430 +:2002980000800804D90001042958A00401800704D8000005D8800045D80000C5D8000085B7 +:2002A0000813F300D809883A014008040184004408100FC0103FEF1E00800044014020749B +:2002A800D8800005D900010400800444295AF28401800344D8800045D80000C5D8000085DB +:2002B0000813F300D809883A014004440184008408100FC01004C03A0085C83ADFC0401779 +:2002B800DEC04104F800283ADEFFB60401000434014002C4D80D883ADFC04915DD404815F4 +:2002C000DD004715DCC04615DC804515DC404415DC0043150810088010000226043FFFC4B1 +:2002C80000003D06D9004004D80B883A018002040814054001402074D90040042956B20402 +:2002D00001800204081401001021883A1000311ED8800203DD4002830023883AD880420595 +:2002D800D8800243DD404285D8804245A8803FCC8880290E8CC400449826923A0140008451 +:2002E000D80D883A9809883A08100880103FE31EDD0000439809883AD80D883AA00B883A6D +:2002E800DC80000308100880103FDC1E90803FCC1000032600C0004410C00826000013063F +:2002F00000800804A080111E010020742118A004D94001040180070400000B06008004441E +:2002F800A0800A1E01002074211AFDC4D9400104018003440813F30001002074211AF284D3 +:20030000D9400104018003440813F3008C400044003FD606040000448005883ADFC0491730 +:20030800DD404817DD004717DCC04617DC804517DC404417DC004317DEC04A04F800283A7A +:20031000DEFFF904DD000415DCC00315DC80021504C020B40480207405002074DC0000159C +:20031800DFC00615DD400515DC4001150021883A9497D5049CC52004A518A0040100207440 +:2003200001402074211AEA042956B40401800444081405408405883A1485883A1140001750 +:2003280001002074211AF5C401800444081405400100207401402074211AEA04295AF5C433 +:200330000812F6000023883A852B883A98800037D0E12A1710BFFFCCD0A12E151800201E61 +:2003380010001F2688000E1E0100207401402074211AEA042956B60401800444A880000DD2 +:20034000081405400100207401402074211AEA04295AF5C40812F6000440004400001006BF +:20034800A8C0000B10C00D260100207401402074211AEA042956B804018004440814054027 +:200350000100207401402074211AEA04295AF5C40812F6000023883A0000010604400084FA +:20035800D0A12E17D0A12A1500800084888003260109C40408148EC0003FD406840000848D +:200360000080070480BFBD1EDFC00617DD400517DD000417DCC00317DC800217DC4001178C +:20036800DC000017DEC00704F800283ADEFFFB0400C0207418DAFA04DCC00315DC80021538 +:20037000DC400115DC000015DFC00415188002832021883AD12001041085883A1085883ACE +:200378002085883A190002C7014007041C80011714C000170813F08000C0207418D7FA0465 +:2003800010C5883A84003FCC1440000B8000311ED0A1290300C003C410BFFFC410803FCCB8 +:2003880018804536100490BA00C0207418C38F0410C5883A108000171000683A00810EC4DF +:2003900000810EC400810F3800810EB400810F3800810F3800810F3800810EA800810F3898 +:2003980000810F3800810F3800810F3800810F3800810F3800810F3800810E7C9809883A27 +:2003A000900B883A0813EF801009883A897FFFCC0813F08000C072B418F0DFC418800236BC +:2003A800010003C4000001060009883A08137400000019060009883A08137400010000444E +:2003B000000016060009883A081374000009883A0000120600802074109AF28410C00303CA +:2003B800044000841021883A1C4002260009883A00000106010003C4081374008100030336 +:2003C00020803FCC8880042E008001441109C83A21003FCC00000106010000C4DFC00417A5 +:2003C800DCC00317DC800217DC400117DC000017DEC00504081321C1DFC00417DCC00317AF +:2003D000DC800217DC400117DC000017DEC00504F800283ADEFFF90421003FCCDFC00615B0 +:2003D800DD400515DD000415DCC00315DC800215DC400115DC0000150813CB00010020B4D3 +:2003E0002105140420C0003704002074841AFA04814003031825D43A202B883A10C03FCC7A +:2003E8002800051E18000F2680800305D02126050440010400000D0618000A1ED0A1260303 +:2003F0000440010410C03FCC88C0032ED0212605800003050000050610800044D0A1260531 +:2003F80000000106D02126050023883A01000DC4081330C001000E041029883A081330C0E7 +:20040000110003CC2008923A1026D17A1006D1BA2528B03A9CC0004C18C0004C80C002455C +:20040800A88000370100008490C03FCC19000926010000441900081EA106983A10BFFFCCB6 +:2004100018FFFF841880042E1029883A0027883A0000010604C0004401000E44081330C017 +:2004180001000E84102B883A081330C0108003CC1006923A8080000F1D6AB03AA0FFFFCCFE +:2004200018E0001C18E000041887C83A1800010E00C7C83A0080004410C0071680C0011712 +:20042800A8C0051E01002074211AFA042100020398C03FCC19000226D0212D4500000B061D +:20043000D0E12D4319003FCC2080082618C00044D0E12D4518C03FCC1880041E88C03FCC6A +:20043800008000841880012E1023883A04802074949AF28490C000C3808004831880051ED3 +:2004400000802074109AFA0490C00103108004C31880042688C03FCC008000841880012E55 +:200448001023883A90C00203808005C318800F2600802074109AFA04110002C701400704D3 +:200450000813F08000C0207418D7FC0410C5883A1080008B1080600C1000042688C03FCC83 +:20045800008000841880012E1023883A91400003810003C300C020740080207485000015A7 +:200460008540011584C0020518DAFA04109AF28429000C1E11400043190004032900091EEF +:2004680011400083190004432900061E11400143190005032900031E11000183188005437E +:200470002080032688803FCC1000011E04400044910002438080060720C03FCC18C0201CF7 +:2004780018FFE004188003262100040421003FCC08137DC0910002838080064320800626D0 +:20048000014006040813F080010020742117EA042089883A0813628091000303808006C303 +:20048800208001260810DAC0910002C38080068320800126081378800100207401402074B8 +:20049000211AFDC4295AF284018003440813F3008805883ADFC00617DD400517DD00041745 +:20049800DCC00317DC800217DC400117DC000017DEC00704F800283ADEFFF804DC00001525 +:2004A00004002074841AFA04DD000415850002C7DCC003150140070404C02074A009883A01 +:2004A800DFC00715DD800615DD400515DC800215DC4001159CD7F6040813F0809885883A4E +:2004B00010C0068B188003CC100006268440044300800084808003458822C03A8822907A79 +:2004B8000000070618C0040C18000326008000448080034500000106800003458440044308 +:2004C00084800343808004C3A009883A902497BA1004973A0140070490A4B03A0813F080C1 +:2004C8009885883A10C00503A009883A0140070490E4B03A0813F0809885883A10C0028B81 +:2004D000808005031806943A1004923A90C6B03A1884B03A00C020B418C51C041880003514 +:2004D800848003C39000251E002B883A858002C70140070485000403B009883A0813F080CE +:2004E0009885883A1080030BA028963AB009883A1004937A01400704882296FAA0A8B03A93 +:2004E8000813F0809885883A10800543A0A8B03A80800543100491BAA084B03A1444B03A89 +:2004F00014A4B03A008020B49564B03A1085180414800035DFC00717DD800617DD40051729 +:2004F800DD000417DCC00317DC800217DC400117DC000017DEC00804F800283A94BFFFC480 +:200500009024973A05480034003FD806DEFFF704DC00031504002074841AFA04DC40041583 +:200508008440011700800044DFC00815DD000715DCC00615DC800515D0A12D4588001F26A1 +:2005100084C0001798001D2680800283D0E00104880B883A1085883A1085883A1885883AF9 +:2005180015000017A009883A0813EF801025883A80800203A009883A0140190410000626A1 +:200520000813F0801009883A880B883A0813EF801009883A000005060813F0801009883A2A +:20052800880B883A0813EF801089883A980B883A0813EF801023883A000002060445DC0464 +:20053000048F550401000EC4081330C001000F04081330C080C00383008020741097CD0470 +:2005380018C7883A18C7883A10C7883A8080020319C0001780C000171000021E00801A446E +:200540000000010600801C040100207401802074D8C000153196BC04211AEE440140044420 +:20054800D88001150813F5808809883A014019040813EF809009883A0140FA041027883AC7 +:200550000813EF809009883A0140FA041029883A0813F0001009883A014002840813EF8035 +:200558008809883A01401904D8800015DCC001150813F0000100207401802074D88002158F +:20056000211B0104014004443196BE04A00F883A0813F580D0A129431000051E0100207482 +:2005680001402074211AEE44295B01040812F600808004838100001781400203D880001546 +:20057000808004C3D1E12F03980D883AD8800115808005C3044020748C5AFA04D8800215F8 +:200578000813CF8011003FCC2100201C213FE00400FFFFC420C0011E00800104888002C527 +:20058000844002C701400704048020748809883A0813F08000C0207418D7FC0410C5883AB2 +:2005880011400003D0E12F0380800203949AFA0428CA703AD161290529403FCC1000022643 +:20059000918000170000020690C00017180CD07A808002838809883A99C03FCCD88000159D +:2005980008138840810006C30810DAC0DFC00817DD000717DCC00617DC800517DC40041743 +:2005A000DC000317DEC0090408112781DEFFFF04DFC0001521003FCC20000B1E010000448B +:2005A800200F883A000B883A000D883A0812ACC001000044000B883A000D883A000F883A6E +:2005B000081257400000050601000044000B883A000D883A000F883A0812ACC00009883A6C +:2005B800DFC00017DEC001040812A6C1D0A12A17DEFFFC04DFC00315DC800215DC4001155E +:2005C000DC00001510000B1E00C0207418D8A004D0A12E171940028B1141A8261940030BE6 +:2005C8001141AD261940040B1141B22618C0038B10C1B22621003FCC2001B2260021883A45 +:2005D000D0A12D030480207494979B04102290FA01002074211AEA049445883A114001170A +:2005D800018004449463883A081405408880000300C0038418818136100490BA00C02074CC +:2005E00018C5E40410C5883A108000171000683A008117CC0081182C008118A8008118EC57 +:2005E8000081193C008119A800811A2000811AB800811AF400811B5400811BB000811BF472 +:2005F00000811C5400811CBC00811D280080207484003FCC00C00104109AF28480C0051EF0 +:2005F80010C0000319003FCC20000A2618FFFFC40000070600C000C480C0061E10C00003FA +:200600000140004419003FCC290002361947883A10C000051080000300C0207418D7C3043C +:200608001085883A1085883A000076060080207484003FCC00C00104109AF28480C0051EBD +:2006100010C0004319003FCC20000A2618FFFFC40000070600C000C480C0061E10C0004361 +:200618000140018419003FCC2900023618C0004410C000451100004301401F4421000044E9 +:200620000813F0801009883A014002840813E4800100207401802074211AF5C401400444E7 +:200628003196CC0400008106843FFF440080207484003FCC00C00044109AF2841C00033672 +:2006300010C000831807003A10C00085108000831000031E018020743196C5040000F306C7 +:20063800018020743196C4040000F0060080207484003FCC00C00104109AF28480C0051E1D +:2006400010C0014319003FCC20000A2618FFFFC40000070600C000C480C0061E10C001432F +:200648000140038419003FCC2900023618C0004410C0014511C001430000130600802074D1 +:2006500084003FCC00C00104109AF28480C0051E10C0018319003FCC20000A2618FFFFC411 +:200658000000070600C000C480C0061E10C001830140038419003FCC2900023618C00044D0 +:2006600010C0018511C0018339CF883A0100207401802074211AF5C4014004443196CE0445 +:2006680039CF883A000042060080207484003FCC00C00104109AF28480C0051E10C00203A0 +:2006700019003FCC20000A2618FFFFC40000070600C000C480C0061E10C0020301400044CD +:2006780019003FCC290002361947883A10C002051080020300C0207418D7C6041085883AEB +:200680001085883A1885883A1140001701002074211AF5C401800444081405400000DD06A6 +:200688000080207484003FCC00C00104109AF28480C0081E10C00243013FFC4419403FCC6B +:200690002940201C297FE00429000C1618FFFFC40000090600C000C480C0081E10C00243E6 +:200698000140038419003FCC2100201C213FE0042900021618C0004410C0024511000247E7 +:2006A00001411944210004040813F0801009883A014019040813E480010020740180207485 +:2006A800211AF5C4014004443196D104100F883A0813F5800000B706843FFF4400802074D1 +:2006B00084003FCC00C00044109AF2841C00033610C002831807003A10C002851100028387 +:2006B800014006040813F08000C0207418D7EA04003FC4060080207484003FCC00C00104AA +:2006C000109AF28480C0051E10C002C319003FCC20000A2618FFFFC40000070600C000C423 +:2006C80080C0061E10C002C30140008419003FCC2900023618C0004410C002C5108002C3C7 +:2006D00000C0207418D7BF041085883A1085883A003FAC060080207484003FCC01000104BC +:2006D800109AF2848100051E10C0030319003FCC2000092618FFFFC40000060600C000C48B +:2006E00080C0051E10C0030319403FCC2140023618C0004410C003051080030300C02074E6 +:2006E80018D7B9041085883A1085883A003F9506843FFF440080207484003FCC00C0004411 +:2006F000109AF2841C00033610C000C31807003A10C000C5108000C31000031E018020745B +:2006F8003196C80400003106018020743196C70400002E060080207484003FCC00C00104D5 +:20070000109AF28480C0051E10C0010319003FCC20000A2618FFFFC40000070600C000C4A3 +:2007080080C0061E10C001030140008419003FCC2900023618C0004410C0010510800103C9 +:2007100000C0207418D7C9041085883A1085883A003F6C06008020B4108520041080003786 +:20071800044020741080012C8C5AF2841000081E843FFF4484003FCC0080004414000436F3 +:20072000890001C32009003A890001C5081168C0888001C31000031E018020743196CA04D2 +:2007280000000206018020743196C90401002074211AF5C40140044400003506843FFF44AD +:2007300084003FCC0080004414001B3608106CC001002074211AEA04014004441000091E2F +:20073800018020743196D3040813F5800100207401802074211AF5C4014004443196D70495 +:2007400000002306018020743196DB040813F5800100207401802074211AF5C401400444FE +:200748003196DD0400001A06843FFF4484003FCC008000441400062E01002074018020747E +:20075000211AF5C4014004443196DF04000010060810A08001002074211AF5C40140044402 +:200758001000031E018020743196E30400000806018020743196610400000506010020749E +:2007600001802074211AF5C4014004443196E5040813F5800100207401402074211AEA0414 +:20076800295AF5C4DFC00317DC800217DC400117DC000017DEC004040812F601D1212D0307 +:20077000014003C404000084210003840813F000D0A12D05003E5A06D1212D03014003C4BB +:2007780004000044210000440813F000D0A12D05003E5306040000C4003E51060400010409 +:20078000003E4F06DFC00317DC800217DC400117DC000017DEC00404F800283AD0A12A17BF +:20078800DEFFFE04DFC0011510005A1E00C0207418D8A004D0A12E171900018B1100071EBC +:20079000D0A129431005003AD0A12945100006260100004408116EC000004E061900020BFC +:200798001100071ED02129450100207401402074211AEE44295B01040812F60000004506F1 +:2007A0001900048B1100201E00802074109AFA04110002C7014007040813F08001C0207480 +:2007A800010020740180207439D7F604211AEA04014004443196E904388F883A0813F580FE +:2007B000008020B41085140411C0003710800037010020741005D43A01802074211AF5C498 +:2007B80001400444D88000153196EC0439FFFFCC0813F5800100207401402074211AEA044E +:2007C000295AF5C4003FDC061900050B1100061E00C020B418C52404188000371080009CCA +:2007C8001880003500001B061900058B1100061E00C0207418DAF284188000031005003A9F +:2007D00018800005000013061900060B1100071E00C0207418DAF2841880004311003FCC40 +:2007D80020000C2610BFFFC40000090618C0068B10C0081E00C0207418DAF2841880004318 +:2007E0000140018411003FCC290002361080004418800045D0A12C171000081ED0A1301763 +:2007E800108000AC1000052600C0207418DAF284188000031005003A18800005D0A129435A +:2007F000100004260009883ADFC00117DEC0020408116EC1DFC00117DEC00204F800283A8C +:2007F800DEFFFD04DC000015040020B4DFC00215DC4001158405240480000035008020B498 +:2008000010851C0410000035008020B410851804100000350109C40408148EC0008000C414 +:2008080080800035010000F42103500408148EC0010020B401406734018001B421050804AB +:20081000297F30043186A00408151E400812E30008131A40100022260009883A081330C076 +:2008180000C03FC410C0202608138280010000840812728010803FCC00C004C410C01C1E0C +:2008200008128180081005C01021883A10001A1E0810AE80008020B41085200410C000372B +:200828000440207418C0012C8C5AFA04180005260100207400C00044211AF28488C0058590 +:2008300020C001C510800037108000AC1000011E0810C40089000583081168C00000070695 +:20083800043FFF8400000506043FFF4400000306043FFF0400000106043FFFC48005883AA6 +:20084000DFC00217DC400117DC000017DEC00304F800283ADEFFFF04DFC00015081140C00D +:200848000813440000802074109AFA0411000583DFC00017DEC00104081168C1DEFFF6046A +:20085000DFC00915DDC00815DD800715DD400615DD000515DCC00415DC800315DC4002150D +:20085800DC0001150811FE0010001E16D0A00003D1E126430100207401802074211AEE448E +:20086000014004443196F004D88000150813F5800100207401402074211B01042956FC040D +:20086800018004440813F3000100207401402074211AEE44295B0104058020B40400207448 +:200870000540207405C020740812F6000029883AB5852004841AFA04AD58A004BDD7CD0433 +:20087800000026060100207401802074211AEE44014004443196F504100F883A0813F58063 +:200880000100207401402074211B01042956CD0401800444081405400100207401402074C9 +:20088800211AEE44295B01040812F600003FFF06A900000B11001B1E808003831080006092 +:2008900010800044D1212C172000292680C0038311003FCC20C0301E0109C40408148EC084 +:200898000811E1C0A0803FCC10008B1ED0A12E17D0A12A15D0A13017D0A12C15B08000376B +:2008A00010BFFFCCD0A12E15B0C0003700C6303A190000ECD1213015D1212A172000101E56 +:2008A800003FE306A900008B1100041E80800383108000E0108000C4003FE206A900010B7B +:2008B0001100071E81000383008001442080062601400184217FDB1E008001C4003FD90698 +:2008B8000005883A003FD70600800184003FD50618C0006C183FD5268080038300C001C47D +:2008C00011003FCC20C0022610800044003FCF0600800044003FCD0610FFFFC418C03FCC81 +:2008C8000140018428C03036180690BA010020742108D0041907883A18C000171800683A77 +:2008D0000081235C0081236C0081238400812394008123A8008123B8008123D000C003C4F5 +:2008D800D0E12F050025883A0000030600C003C4D0E12F0504800084044000440027883A46 +:2008E00000001A0600C003C4D0E12F05048000C40000030600C003C4D0E12F0504800084A7 +:2008E8000023883A003FF50600C00404D0E12F05048000440000030600C003C4D0E12F05E7 +:2008F0000025883A044000848827883A000007060480008400C003C4D0E12F059023883AD2 +:2008F8009027883A00000106203F9B26814006C3808003858000030528803FCC00C00044EF +:2009000089003FCC1880042E00800144114BC83A29403FCC00000106014000C40813290092 +:2009080008133F408180028399003FCC91403FCC0813B6C08080038301002074211AEE4416 +:200910001085883A1085883AB885883A11400017018004448000011508140540010020745D +:2009180001402074211B01042956F9040180044408140540D0A129431000051E010020745E +:2009200001402074211AEE44295B01040812F60005000044003F700699003FCC0810F540ED +:2009280010803FCC00C0008410C0272600C0010410C0032600C0004410FF6C1E0000290629 +:20093000808003031000072600C020B418C52404188000371080011418800035081211401F +:20093800003F62068000011508133F408080038301002074211AEE441085883A1085883A92 +:20094000B885883A1140001701800444081405400100207401402074211B01042956F904DF +:200948000180044408140540D0A12943103F4F1E0100207401402074211AEE44295B01046C +:200950000812F600003F490680800303103F47268080001700C018C418BF442E081140C012 +:20095800003F420680800303103F402608112780003F3E06DEFFFB0400BFE084D88000059E +:2009600000800084D880004500800344D8800085DFC0041529403FCC008000442880042670 +:20096800008000842880041E008014040000030600800C040000010600800404D88000C5C4 +:20097000D88000C331803FCC10800094D88000C530000226008008040000010600800404DC +:2009780039C03FCC10C002143800022600BFE00400000106008010041884B03AD8800105F3 +:20098000D90001850080020401000044D80B883AD8800145D80001C5D8000205D80002454E +:20098800D8000285D80002C5D8000305D8000345D8000385D80003C5081293C0DFC004172A +:20099000DEC00504F800283ADEFFFC04DC000015040020B484050804DC80021504801304FD +:20099800DC400115900B883A2023883A000D883A8009883ADFC00315081525808009883ACD +:2009A00089403FCC000D883A08152BC0044000448009883A900B883A880D883A0815258043 +:2009A8008009883A880B883ADFC00317DC800217DC400117DC000017DEC00404081529014D +:2009B000DEFFFC04DC000015040020B484050804DC800215DC4001152025883A2823883A33 +:2009B8008009883A01401304000D883ADFC00315081525808009883A91403FCC000D883A3E +:2009C00008152BC08009883A89403FCC01800044DFC00317DC800217DC400117DC000017D6 +:2009C800DEC0040408152BC1DEFFFF0421003FCCDFC0001508126480DFC00017DEC0010449 +:2009D000F800283ADEFFFF0421003FCC29403FCCDFC0001508126C000005883ADFC0001776 +:2009D800DEC00104F800283ADEFFFB04DCC00315DC800215DC400115DC000015DFC0041524 +:2009E0002827883A3023883A2025883A0021883A8440070E9C05883A114000038489883A88 +:2009E80021003FCC08126C0084000044003FF8060005883ADFC00417DCC00317DC8002178C +:2009F000DC400117DC000017DEC00504F800283ADEFFFF040140FA04DFC000150813F08061 +:2009F8001009883ADFC00017DEC0010408148EC1DEFFFF04010003C4000B883ADFC0001517 +:200A00000812744001001844000B883ADFC00017DEC0010408127441DEFFFD04DC000015E7 +:200A080004002074841B06048140008301000144DFC00215DC4001150812744080800083CA +:200A10008100030300FFFEC41004D1FA20C6703A044001041085883A1085883A1884B03A92 +:200A18008809883A01400F4480800305081274400100004408127D008809883A0140074446 +:200A2000081274400100184401400C04081274400100024401402C840812744001000284DF +:200A280001403E0408127440010002C401400DC408127440010003C4000B883A0812744053 +:200A300001003244000B883A0812744001003284000B883A08127440010032C4000B883A7E +:200A38000812744001003304000B883A0812744001003344000B883A081274400100338432 +:200A4000000B883A08127440010033C4000B883A0812744001003404000B883A0812744094 +:200A48008140010301003844DFC00217DC400117DC000017DEC0030408127441DEFFFE041A +:200A5000DFC00115DC00001521003FCC2000031E01003344000B883A00003C062821883AE1 +:200A580028003D26010003C40140004408127440814000C3010016040812744081400103A6 +:200A6000010016440812744081400143010016840812744081400183010016C408127440F1 +:200A6800814001C3010017040812744081400203010017840812744081400243010017C4ED +:200A700008127440814002830100180408127440814002C3010018440812744081400303EF +:200A7800010018840812744081400343010018C4081274408140038301001904081274400E +:200A8000814003C30100194408127440808000C4000B883A8400040410C0000310800044DF +:200A880028CBC83A143FFC1E29401BC40100174429403FCC08127440010003C4000B883A71 +:200A90000812744001003344014000C40812744000800044000001060005883ADFC00117E4 +:200A9800DC000017DEC00204F800283ADEFFFD04DC000015000B883A2021883A010003C4E6 +:200AA000DFC00215DC40011508127440044030448809883A0812728084003FCC800AC03A56 +:200AA80010803F8C8809883A114AB03A0812744001003184014000C4DFC00217DC400117C6 +:200AB000DC000017DEC0030408127441DEFFF904DD000415DC800215DC4001152025883A43 +:200AB8002823883A010001040140074405002074A51B0604DCC00315DC000015DFC00615BD +:200AC0003821883ADD4005153027883A08127440A0C0030381C0004C00BFFF441884703AA2 +:200AC80039CF883A11CEB03AA1C00305A08003171080008C10000226010000440812A6C0BF +:200AD00001001C04A40000C308127280108000CC8D4000CC01000044100B883AA900052687 +:200AD80001000084A900041E00FFE00410CAB03A00000106114010148080020C1000012646 +:200AE000294008148080004C10000126294004148080008C10000126294002148400010C9A +:200AE800800001262940011401001C0429403FCC08127440A800141E9CC000CC00800044A0 +:200AF0009880092698003E260080008498800E1E88803FCC1080201C10BFE00410000D1696 +:200AF8000027883A00000C0688803FCC1080201C10BFE0048CC0100C1000070E00BFE80419 +:200B000014E6B03A000004060021883A0027883A00002D0604FFE8048C400C0C0080080489 +:200B08008880142600800C0488800A26008004048880181E01001CC4D1600304018000C49F +:200B1000081276800140207401001D842958A7040000170601001CC4D16003C4018000C4D7 +:200B1800081276800140207401001D842958AB8400000F0601001CC4D16003C4018000C453 +:200B2000081276800140207401001D842958B4840000070601001CC4D1600304018000C40A +:200B2800081276800140207401001D842958B0040180048408127680040000840000020648 +:200B30000027883A0021883A01001C84081272801080070C9C20B03A140AB03A01001C843A +:200B380029403FCC08127440A0800317010030041080008C1000022601400044000001060C +:200B4000000B883A0812744001000104014005440812744001001844014004040812744028 +:200B480094803FCC00800084010018849080081E0140220408127440010018C4014004043C +:200B5000081274400100190401402104000007060140060408127440010018C401400404E7 +:200B5800081274400100190401400304081274400100004408127D0001000104081272808D +:200B60001140074C01000104081274400100190408127D0001000104081272800100010430 +:200B68001140054C081274400400190401000384081272801080040C1000061E010000442F +:200B700008127D0080BFFFC41021883A10BFFFCC103FF61E01000304000B883A0812744039 +:200B780001000344014010040812744001000384014000440812744001000384000B883AC2 +:200B80000812744008127F0000800044DFC00617DD400517DD000417DCC00317DC80021712 +:200B8800DC400117DC000017DEC00704F800283ADEFFFA04DC800215048020B4DFC00515C4 +:200B9000DD000415DCC00315DC400115DC0000159485100490000035044005048809883AE6 +:200B9800040020B48405080408148EC08009883A01400E04081531808809883A08148EC03D +:200BA0008009883A01400E44081531808809883A08148EC0880B883A8009883A081531805E +:200BA8008809883A08148EC08009883A01401C44081531808809883A08148EC08009883AAE +:200BB00001401784081531808809883A08148EC08009883A01401B44081531808809883AB2 +:200BB80008148EC08009883A01400304081531808809883A08148EC004C00044980B883A28 +:200BC0008009883A081531800500C804A009883A08148EC08009883A014001840815318077 +:200BC8008809883A08148EC08009883A0140008408153180A009883A08148EC094C0003514 +:200BD000DFC00517DD000417DCC00317DC800217DC400117DC000017DEC00604F800283AFE +:200BD800DEFFFA04DC000015040020B4DCC00315DC800215DFC00515DD000415DC40011551 +:200BE0002027883A2825883A8405100480000035010020B401400044210508040815318031 +:200BE8000100C80408148EC000800084808000359809883A0140040408140A001007883AD2 +:200BF00010803FCC1000061E014020749809883A2957E304018004440814054000C0004449 +:200BF8009829883A1C403FCCA1400007010020B421050804081531800100050408148EC0C2 +:200C0000A5000044A4C5C83A10803FCC147FF63680000035010020B40140300421050804F5 +:200C0800081531800100050408148EC000800084808000359009883A0140040408140A0087 +:200C10001007883A10803FCC1000061E014020749009883A2957E30401800444081405405B +:200C180000C000449027883A1C403FCC99400007010020B421050804081531800100050419 +:200C200008148EC09CC000449C85C83A10803FCC147FF636008000C480800035DFC00517F9 +:200C2800DD000417DCC00317DC800217DC400117DC000017DEC00604F800283ADEFFFB0484 +:200C3000DC000015040020B484050804DC80021504800B04DCC00315900B883A2027883A26 +:200C3800000D883A8009883ADFC00415DC40011508152580044000448009883A99403FCC1F +:200C4000880D883A08152BC08009883A900B883A880D883A081525808009883A880B883AD4 +:200C4800DFC00417DCC00317DC800217DC400117DC000017DEC0050408152901DEFFFC04B5 +:200C5000DC000015040020B484050804DC800215DC4001152025883A2823883A8009883A22 +:200C580001400B04000D883ADFC00315081525808009883A91403FCC000D883A08152BC0E6 +:200C60008009883A89403FCC01800044DFC00317DC800217DC400117DC000017DEC0040495 +:200C680008152BC1010020B4DEFFFD04000D883A000B883A21050804DFC00215DC400115FA +:200C7000DC00001508152BC00100028408148EC004000604044000448809883A800B883A44 +:200C7800081313C0800B883A01000084081313C0800B883A010000C4081313C08809883A5B +:200C800008130BC01405003ADFC00217DC400117DC000017DEC00304F800283ADEFFFC0460 +:200C8800DC4001152023883ADC8002158C403FCC048000449009883A882290FADFC00315BD +:200C9000DC00001508130BC0043FF9C41404703A1460B03A84003FCC9009883A800B883A16 +:200C9800081313C0800B883A01000084081313C0010000C4800B883ADFC00317DC8002174E +:200CA000DC400117DC000017DEC00404081313C1DEFFFD04DC4001152023883A010000441E +:200CA800DC000015DFC00215043FF60408130BC01420703A89003FCC008000842080021E2C +:200CB00084000054000003062008917A2080011480A0B03A84003FCC800B883A0100004430 +:200CB800081313C0800B883A01000084081313C0010000C4800B883ADFC00217DC40011770 +:200CC000DC000017DEC00304081313C1DEFFFB04DC000015040020B484050804DC800215E0 +:200CC80004801704DCC00315900B883A2027883A000D883A8009883ADFC00415DC4001154F +:200CD00008152580044000448009883A99403FCC880D883A08152BC08009883A900B883A84 +:200CD800880D883A081525808009883A880B883ADFC00417DCC00317DC800217DC4001172A +:200CE000DC000017DEC0050408152901DEFFFC04DC000015040020B484050804DC80021565 +:200CE800DC4001152025883A2823883A8009883A01401704000D883ADFC0031508152580B7 +:200CF0008009883A91403FCC000D883A08152BC08009883A89403FCC01800044DFC0031749 +:200CF800DC800217DC400117DC000017DEC0040408152BC1DEFFFE04DC0000150409C404EC +:200D00008009883ADFC0011508148EC0014004C401000584081338C08009883A08148EC00E +:200D0800010005C4014000C4081338C08009883ADFC00117DC000017DEC0020408148EC1E5 +:200D1000DEFFFE04DC0000150409C4048009883ADFC0011508148EC00140044401000584A1 +:200D1800081338C08009883A08148EC0010005C401400084081338C08009883ADFC001174F +:200D2000DC000017DEC0020408148EC1DEFFFA04DC0000152021883A01000104DD000415E6 +:200D2800DCC00315DC8002153829883ADFC00515DC4001152827883A3025883A081330C043 +:200D300000FFFE04A5003FCC10C4703AA00006261080005411403FCC01000104081338C04F +:200D38008423883A0000040611403FCC010001048023883A081338C08C7FFFCC880AD13ADB +:200D40000100004429403FCC081338C0880A913A0100008429403C0C081338C0993FFFCC7E +:200D480091403FCC0813F0801009883A880B883A0813F0801009883A0140FA040813EF80C5 +:200D500000E327D41880092E00C0007418C45BC41880082E00C000B418C3D5C41885403ADA +:200D580000C000C41885C83A000003060005883A000001060080004414003FCCD0A00484A6 +:200D60001405883A1100000301400A040813F0808808D07A880B883A1109883A0813E48020 +:200D680010803FCC100A90FA800491BA010000C4288AB03A29403FCCDFC00517DD000417D5 +:200D7000DCC00317DC800217DC400117DC000017DEC00604081338C1DEFFFE04DC00001585 +:200D78002021883A01000684DFC00115081330C0017FFE8484003FCC00C000441144703A79 +:200D800080C0021E10800094000001061080029411403FCC01000684DFC00117DC00001711 +:200D8800DEC00204081338C12140028BDEFFFE04DC000015280AD23A2021883A010012C4BD +:200D9000DFC00115081338C08140028301001284081338C08140030B01001344280AD23A26 +:200D9800081338C08140030301001304081338C08140038B010013C4280AD23A081338C0BE +:200DA0008140038301001384081338C08140010B01001444280AD23A081338C08140010305 +:200DA80001001404081338C08140018B010014C4280AD23A081338C08140018301001484AA +:200DB000081338C08140020B01001544280AD23A081338C08140020301001504081338C0A4 +:200DB8008140040B010015C4280AD23A081338C08140040301001584081338C08140048B5B +:200DC00001001644280AD23A081338C08140048301001604081338C08140050B010016C445 +:200DC800280AD23A081338C08140050301001684DFC00117DC000017DEC00204081338C1F4 +:200DD000DEFFFD04DC00001504000FC4DC4001152023883A8009883ADFC00215081330C01A +:200DD80000FFFC0410C4703A888AB03A8009883A29403FCCDFC00217DC400117DC000017E4 +:200DE000DEC00304081338C1DEFFFD04DC40011504400684DC0000152021883A8809883A15 +:200DE800DFC00215081330C081403FCC00C000C4194BC83A280A91BA10800FCC8809883A39 +:200DF000114AB03A29403FCCDFC00217DC400117DC000017DEC00304081338C1DEFFFD04B4 +:200DF800DC0000152021883ADC40011584003FCC044001048809883A802090FADFC00215AA +:200E0000081330C0108001CC140AB03A8809883A29403FCCDFC00217DC400117DC000017BC +:200E0800DEC00304081338C1DEFFFF04DFC0001508133F40000B883A01000D44081338C0B1 +:200E1000010020742117EA04081362800100040408137DC00009883A081374000009883A84 +:200E18000813788001000F4401400184081338C00100044401401104DFC00017DEC0010482 +:200E2000081338C1DEFFFB04DC4001152023883AD9000503DC0000152821883ADCC00315FA +:200E2800DC800215DFC004153027883A3825883A843FFFC408135D8080803FCC00C003C437 +:200E300018802836100490BA00C0207418CE370410C5883A108000171000683A0081391C13 +:200E38000081393400813964008139340081396400813964008139640081394C0081396422 +:200E40000081396400813964008139640081396400813964008139640081393401000144AA +:200E480001400084081338C001000184200B883A00000B060100014401400184081338C00F +:200E50000100018401400404000005060100014401400C84081338C00100018401400804AB +:200E5800081338C0010006C401402204081338C00100070401400204081338C00100028435 +:200E600001400684081338C00100024401400684081338C00100020401400684081338C08A +:200E680080803FCC00C003C418802236100490BA00C0207418CE710410C5883A108000179D +:200E70001000683A00813A0400813A1400813A3400813A1400813A3400813A3400813A3497 +:200E780000813A2400813A3400813A3400813A3400813A3400813A3400813A3400813A34F2 +:200E800000813A1401000C4401400244081338C000002D0601000C4401400604081338C0B6 +:200E88000000040601000C4401401684081338C000001F0684003FCC008003C41400283694 +:200E9000802090BA00802074108E960480A1883A808000171000683A00813AC800813AC85A +:200E980000813AE000813AC800813AE000813AE000813AE000813AB000813AE000813AE0AA +:200EA00000813AE000813AE000813AE000813AE000813AE000813A98010008840140030403 +:200EA800081338C001000D04014000C400000B060100088401400204081338C001000D04F6 +:200EB00001400384000005060100088401400204081338C001000D0401402204081338C0DC +:200EB8008C403FCC8C40201C8C7FE0048809883A01400704040020740813F0808417F604F5 +:200EC0008087883A19C0068B1900040B91803FCC39C0100C380EC03A997FFFCC081348C040 +:200EC8000100048401400044081338C0010004C4000B883A081338C08809883A01400704A1 +:200ED0000813F0808085883A11400583010001C4DFC00417DCC00317DC800217DC400117F8 +:200ED800DC000017DEC00504081338C1DEFFFC0429FFFF84DC800215DC400115DC0000152E +:200EE000DFC0031539C03FCC008000443025883A24403FCC2C003FCC11C0043600800084A7 +:200EE8008880071E8805883A000008068800061E8005003A00C000841885C83A0000030609 +:200EF0000005883A0000010600800084880A913A8C47883A10803FCC18CF883A100491BA7B +:200EF80029C6B03A20CAB03A288AB03A0100064429403FCC081338C091003FCC048000841B +:200F000008135D809400032E008000C480800526000009060100040401401604081338C01F +:200F0800000005060100040401401744081338C08C800B1E000007068C80091E844008269F +:200F1000008000448080031E01000384014014840000050601000384014014C400000206C7 +:200F180001000384014016C4081338C001000504081330C0008000C4010006048080021E7F +:200F20000140040400000106000B883A081338C001000D84000B883ADFC00317DC800217F4 +:200F2800DC400117DC000017DEC00404081338C1DEFFFE04DC0000152021883A01000504EB +:200F3000DFC00115081330C084003FCC00C0008480C0031E1080260C1080204800000206EB +:200F38001004D07A1080004CDFC00117DC000017DEC00204F800283ADEFFFE04DAC0030338 +:200F400002800044DC00001552D6983ADA400403DC00020302002074DC4001154217FC04BD +:200F48000005883A037FFEC40380008403FFFBC429403FCC030005844180008B40C0000367 +:200F50003440200C880005264800021E78C6703A000009064B80081E000006063440400C12 +:200F5800880005264800021E68C6703A000002064A80011E0007883A19C6703A18C03FCC60 +:200F600018000C2630C0080C1807003A28C0091E40FFFE8B18C0078419000636318003CCBB +:200F68008000032630FFFFCC180001261AC007263000062610C000441805883A18C03FCC4E +:200F7000420007041B3FDC1E00BFFFC4DC400117DC000017DEC00204F800283A2900182EAA +:200F7800280017160080080400C00044000002061000112628000516294B883A10BFFFC41A +:200F800018C7883A293FFA3618000B260005883A214002362149C83A10C4B03A1806D07ADD +:200F8800280AD07A183FFA1E3000011EF800283A2005883AF800283A0005883A003FFA066E +:200F900000C00044003FF106DEFFFE04DFC00115DC00001520000B160021883A28000C1614 +:200F9800000D883A0813DDC00407C83A1884F03A1405883ADFC00117DC000017DEC00204B6 +:200FA000F800283A0109C83A04000044283FF40E014BC83A8400005C003FF106DEFFFD04D8 +:200FA800DFC00215DC400115DC00001520000C160023883A0021883A28000D160180004436 +:200FB0000813DDC01404F03A8885883ADFC00217DC400117DC000017DEC00304F800283A7A +:200FB8000109C83A04400044043FFFC4283FF30E014BC83A003FF106000D883A0813DDC10B +:200FC000018000440813DDC10005883A2000072620C0004C2008D07A180001261145883A8A +:200FC800294B883A203FFA1EF800283AF800283A2005883A0007883A1980062628C9883A80 +:200FD00021C0000310C9883A18C0004421C00005003FF906F800283ADEFFF504DFC0091555 +:200FD800DC400815DC000715D9C00A15008020741099AE04144000172800040E008022C496 +:200FE0008880001500BFFFC400001C0600C08204D8C0000DD9000415D90002152800022613 +:200FE80028FFFFC4000001060007883AD8C00515D8C003151100001700FFFFC4D8C0008DBE +:200FF00000C0207418D1A7042821883AD9C00A04D80B883AD8C00115D800061508141300D2 +:200FF80000FFFFC410C0020E00C022C488C0001580000226D8C0041718000005DFC00917FD +:20100000DC400817DC000717DEC00B04F800283A30000E2631BFFFC4218D883A2080000766 +:2010080028C0000710C0011E2180041E2080000328C0000310C5C83AF800283A103FFB26F8 +:201010002100004429400044003FF4060005883AF800283A2005883A2007883A1809883AA1 +:201018003000092629C0000331BFFFC418C0004421C0000539C03FCC39C0201C39FFE00463 +:2010200029400044383FF51E198D883A198003261800000518C00044003FFC06F800283A7B +:20102800214B883A2005883A1140021E1105C83AF800283A10C00007183FFC26108000448C +:20103000003FF906DEFFFB04DC800315DC400215DC000115DFC004152025883A2823883A21 +:20103800D98000053821883A04000A0E888001179009883A880B883AD80D883A01C0004487 +:20104000103EE83A843FFFC4103FF72600BFFFC4000001060005883ADFC00417DC800317AE +:20104800DC400217DC000117DEC00504F800283ADEFFE304D8C00804DF001B15DDC01A151B +:20105000DD801915DD401815DD001715DCC01615DC801515DC401415DC001315DFC01C153C +:201058002029883A2823883A3839883AD9800F150021883AD8000E15002F883A002B883AF4 +:201060000027883A0025883AD8000C15D8000B15002D883AD8C00915D8C00F171900000330 +:2010680020803FCC1080201C10BFE00410012E2601400044B14014262D800216B000062688 +:201070000001250601400084B1401D26014000C4B1402B26000120060140094411410D26BA +:2010780088800117D9000005880B883AA009883AD80D883A01C00044103EE83A1000E81E68 +:20108000840000440001140601400C0411410A260140094411400A1ED88000058880011716 +:20108800A009883A880B883AD80D883AB00F883A103EE83A1000DA1E840000440001050614 +:2010900025BFF404B5803FCC00C002441D80093600BFFFC4908004269009883A0140028464 +:201098000813F080000001060005883A15A5883A0000F20601400B841140F4260580008427 +:2010A000213FF40420C03FCC0100024420C00B3600BFFFC4988006269809883A0140028495 +:2010A800D8C011150813F080D8C01117000001060005883A10E7883A0000E70601401B044B +:2010B0001140E026013FFFC499000226D8000B150000010604C0004401001A441100162652 +:2010B80020800916010018C4110096260100190411001126010016041100D61E00C0004425 +:2010C000D8C00E150000140601001CC41100A6262080041601001BC41100CE1E054002049B +:2010C80000000E0601001D4411000C2601001E04110009260000C706E0800104B8000726D5 +:2010D000D8800D15E7000017E000080E0739C83A020000440000060605400404E0C001040C +:2010D800D8C00D15E7000017002F883A0011883A002D883ADD87883AE0001A26E009883A9C +:2010E000A80B883AD8C01115DA0012150813EF80A809883A100B883AD88010150813F080DA +:2010E800E085C83A01000244D8C01117D9801017DA0012172080021617000C04000005060D +:2010F000D9400E172800022617000DC400000106170015C41F000005B58000443039883AAB +:2010F800003FE4061EC5C83AD8800A159885C83A1839883A00800E0E182D883A1885883A1F +:2011000001000C04D9400917B007883AB140052EB580004419000005B039883AB0BFF91E20 +:2011080000000106B039883AB6EDC83ADD800A15D8800A171207883A90EDC83AD8C00B1767 +:201110001800172640000A2600800B44D880080588800117A009883A880B883AD980080481 +:2011180001C00044103EE83A10004D1E840000440580070EA009883A880B883A01800C0414 +:20112000B00F883A08140C401000451E85A1883AD9000A17E007883A272DC83A000022064A +:201128000580090EA009883A880B883A01800804B00F883ADA00121508140C40DA001217D1 +:201130001000371E85A1883A403FF12600800B44D880080588800117A009883A880B883AA8 +:20113800D980080401C00044103EE83A10002C1E84000044003FE60618FFFFC418800003FB +:20114000A009883AD8C01115D880080588800117880B883AD980080401C00044103EE83AB2 +:20114800D8C0111710001E1E80C5C83A1D89883AE085883A013FF0161021883ADF000D1769 +:2011500000004406010000442480080E95BFFFC4A009883A880B883A01800804B00F883A51 +:2011580008140C4010000E1E85A1883AE0800017A009883A880B883AD88000058880011737 +:20116000D80D883A01C00044E5800104103EE83A1000031E84000044B039883A00002D0612 +:2011680000BFFFC400003106E5800017E0C00104D8C00A15B009883A081479809091C83A23 +:201170001039883A0200090E400F883AA009883A880B883A01800804DA00121508140C4074 +:20117800DA001217103FEE1E8221883A88800117A009883A880B883AB00D883AE00F883A84 +:20118000103EE83A103FE61E8721883ADF000A170000100605C0004404FFFFC4D8000E1542 +:20118800054002849825883AD8000C15D8000B15B82D883A00000806DD800B1505800084D1 +:201190000000050600C00044D8C00C15058000C400000106002D883AD8C00F1718C000445E +:20119800D8C00F15003ECC068005883ADFC01C17DF001B17DDC01A17DD801917DD4018179A +:2011A000DD001717DCC01617DC801517DC401417DC001317DEC01D04F800283A2880000BBA +:2011A800DEFFFD04DC000015DFC00215DC40011510C0020C2821883A1800192628C0008FB9 +:2011B0001800150E10C0800C180013262C40051789C0030E10C0200C1800032600000E0604 +:2011B8003C40010E3823883A81000417300B883A880D883A08147380808005171445C83AF9 +:2011C00080800515808004171463883A844004150005883A00000306108010148080000D33 +:2011C80000BFFFC4DFC00217DC400117DC000017DEC00304F800283A2005883A29000D2E5C +:2011D000298F883A21C00B2E3007883A017FFFC418FFFFC4194006261989C83A3909883A28 +:2011D8002200000310C9883A22000005003FF806F800283A0007883A1980062628C9883A38 +:2011E00021C0000310C9883A18C0004421C00005003FF906F800283A2005883A10C0000718 +:2011E8001800022610800044003FFC061105C83AF800283ADEFFFF040100207401402074D6 +:2011F000DFC000152118A0042959B7042140061E0100207401402074210008042940080480 +:2011F8002140141E00000D0600C0207418D9B70400BFFF041907C83A1886703A0005883A3E +:2012000010FFF326114F883A39C00017110D883A1080010431C00015003FF9060100207426 +:201208000140207421165804295658042140121E00000D0600C0207418C0080400BFFF04E5 +:201210001907C83A1886703A0005883A10FFF326114F883A39C00017110D883A10800104BE +:2012180031C00015003FF90608153BC0DFC00017DEC0010408154B4100C0207418D8A00470 +:2012200000BFFF041907C83A1886703A0005883A10FFF526114F883A39C00017110D883A7F +:201228001080010431C00015003FF906DEFFFF040009883ADFC0001508148F000814910016 +:201230000100207421189004200B883A200D883A08155580D1213417D1613317D1A13217FA +:20123800DFC00017DEC00104081213C1081533C1DEFFFF04DFC0001508157F00008000444A +:201240001001703ADFC00017DEC00104F800283ADEFFFE04DC000015040020748419B00467 +:2012480001002074800B883A21193304DFC0011508153C80010020742118FC040814FFC0FC +:20125000010020742118F104800B883ADFC00117DC000017DEC0020408153C810140207471 +:20125800DEFFFF042959B004DFC000150815440010000E2610C00A17D0A13715D021411512 +:2012600019008D04D1213F1519008904D1213E1519008404D1213D1519008C04D1213C15C2 +:2012680019008B04D1213B15D0E13A15DFC00017DEC00104F800283AD0E137170080004406 +:201270001800041ED0E141171880071ED021411500000506D0E13F1718C0002B18C0008C9E +:20127800183FF826F800283A0005883AF800283ADEFFFD04DC400115DC000015DFC00215AF +:201280002023883A2821883A08149B801000021E0005883A000011068C09883A2006927A70 +:20128800D0A13B1710C00035D0A13C1700C0060410C0002DD0A13F171080002B10BFFFCCD7 +:2012900010C0010C183FFB1E1080040C103FF01ED0213615D121351500800044DFC0021700 +:20129800DC400117DC000017DEC00304F800283AD0A1361710000326D1213517000B883A0E +:2012A00008149F0100800044F800283ADEFFFD04DC400115DC000015DFC002152023883A98 +:2012A8002821883A08149B801000021E0005883A00001906D0A136171000081E8C09883A83 +:2012B0002006927AD0A13B1710C00035D0A13C1700C0044410C0002D00000506D121351712 +:2012B800000B883A08149F00103FF41E003FEF06D0A13F171080002B10BFFFCC10C0010C00 +:2012C000183FFB1E1080040C103FE81ED0213615D121351500800044DFC00217DC40011781 +:2012C800DC000017DEC00304F800283A2005883A2100001711C0021721000A040814B541CA +:2012D0002005883A2100001711C0021721000A040814BB0121000017298D883A2805883A4F +:2012D8003A10000C11800B2E20C000371A60000C4800032610C0000510800044003FF906E1 +:2012E000114002261145C83AF800283A403FF52600000106117FFB1E39D0000C3800021E0C +:2012E80000BFFEC4F800283A00BFFD44F800283A210000173005883A298D883A21C0010424 +:2012F0002980072E38C0003718FFFFEC183FFC2628C0000720C0003529400044003FF80668 +:2012F800F800283A20001D262804923A20C03017DEFFFD04DC400115DC000015DFC0021543 +:201300002823883A2021883A108000D41880033580C03017188000371080004C100003261E +:2013080001000044081533C0003FF90618C000371809D0FA2140020C1809D0BA1807D07AB5 +:20131000210001CC2908B03A18C0040C20C6B03A1C40042600BFF4840000020600BFFA84FA +:20131800F800283ADFC00217DC400117DC000017DEC00304F800283A20000A2628000926D6 +:201320003000082620800C173080001520800C171000062621000D04290000150005883A91 +:20132800F800283A00BFFA84F800283A00BFFEC4F800283A2005883A20001D262809883A9C +:2013300028001B1610C0311728C0192E1140341728FFFFC420C6703A1800151EDEFFFE04BD +:20133800DC000015DFC001151021883A0813EF801004923A00C0403418FFC00410C4703A05 +:2013400080C03017108000941880033580C0301718C00404188000371080004C10000626C4 +:20134800008000441880003500BFFEC40000020600BFFA84F800283ADFC00117DC0000172A +:20135000DEC00204F800283ADEFFF504DC000115DFC00A15DF000915DDC00815DD800715C9 +:20135800DD400615DD000515DCC00415DC800315DC400215DC000B17280039163023883A60 +:20136000300037162027883A20003526382B883A38003326208031173080312E2880302EB9 +:20136800208034172987C83A1887883A1C002C3680002B1610BFFFC4288A703A2800281ECC +:201370000029883A05BFFFC405C000C40700010480002126DD800015890000CC200005267D +:20137800E125C83A8480012E8025883A8923C83A00000406BC0002368025883A0000010699 +:2013800004800104AD0B883AD909883A900D883A0813F30098802E17D8C00017A4A9883A1E +:2013880084A1C83A8885883A10C00035988030171080040410C0003718C0008C18000426A6 +:2013900000C0008410C0003500BFFEC4000005068C400104003FDE060005883A00000106A6 +:2013980000BFFA84DFC00A17DF000917DDC00817DD800717DD400617DD000517DCC0041718 +:2013A000DC800317DC400217DC000117DEC00B04F800283ADEFFF604DC000115DFC0091501 +:2013A800DDC00815DD800715DD400615DD000515DCC00415DC800315DC4002152021883A64 +:2013B00020000A263029883A3000082620802E1780C02F172823883A2885883A382B883A48 +:2013B80011C9883A10C0012E20C0023600BFFA84000024062809883A81403417002D883A0D +:2013C0000813EF80102F883A80803317B8801C2EA8001B2684C0341704E7C83A8CE6703A35 +:2013C8009C4002268CE5C83A000001060025883A8009883A980B883A0814CB401000111E8A +:2013D00080C034171CA5C83AAC80012EA825883ADC8000158009883A980B883A880D883A4D +:2013D800A58F883A0814D4801000061EACABC83AB4AD883A8CA3883ABDC00044003FE20606 +:2013E0000005883ADFC00917DDC00817DD800717DD400617DD000517DCC00417DC800317D0 +:2013E800DC400217DC000117DEC00A04F800283A200007263000062620802E17288B883AB3 +:2013F00020802F1729C7883A2880012E1880023600BFFA84F800283ADEFFFF043009883A2C +:2013F800380D883ADFC000150813F3000005883ADFC00017DEC00104F800283A20005026FC +:20140000208030171000502620C03217DEFFFB04DFC00415DCC00315DC800215DC40011549 +:20140800DC00001518001E1E1480023700C0030494803FCC90BFFAC418804536100490BA4E +:2014100000C0207418D4150410C5883A108000171000683A008150C0008150D0008150D898 +:20141800008150C800815088008151500081515000815150008151500081515000815150F6 +:201420000081509000815098044080040000130604410004000011060442000400000F0642 +:20142800148001370080058494803FCC90800A260080060490800426008005049080241ED1 +:201430000440080400000506044040040000030604401004000001060440200424C03417BA +:201438002021883A8809883A980B883A0813F08080C0311710C0021E80C0331788C00226DC +:2014400080000C150000120600C0004401402074848036158440331580C00C1580000D159C +:2014480080800E1584400F1584C010158009883A2959B50408153C800005883A00000506DF +:2014500000BFFA84F800283A00BFFB44F800283A00BFFB44DFC00417DCC00317DC800217AA +:20145800DC400117DC000017DEC00504F800283A300001260005C03200FFFF042005883A15 +:2014600028C6703A110DC83A30C0042E11800017300DC0F210800104003FFA06294000CCF2 +:2014680000C000C428C0041E10C0000B1807C0B2108000830000080600C0008428C0031EFC +:201470001080000B1005C0B20000040600C0004428C0021E108000031005C0720005C13252 +:20147800F800283ADEFFFD04DC400115DC0000152823883A2021883A014001443009883A68 +:20148000DFC002150813F0808809883A100B883A0813EF8010BFFFC480C00204180000352C +:20148800010000448100043511003FCC810000351004D23A10803FCC8080013500802004DE +:2014900018800035DFC00217DC400117DC000017DEC00304F800283A3180004C294B883A5E +:20149800298B883A21400335210004040080240420800035208000371080008C103FFD1E22 +:2014A000208000371004D1FA1080004CF800283A20C004042800022600801A040000010663 +:2014A8000080080418800035188000371080008C103FFD1E20800337F800283A29403FCCCE +:2014B00021400335210004043000022600801404000001060080040420800035208000372F +:2014B8001080008C103FFD1E208000371004D1FA1080004CF800283A20C0040400800B042B +:2014C00018800035188000371080008C103FFD1E20800337F800283A29403FCC21400335A9 +:2014C800210004040080070420800035208000371080008C103FFD1EF800283A014AAAF4DB +:2014D000DEFFFE04296AAA84DC000015DFC001152021883A0813EF8010000F26016000344F +:2014D800013555740007883A297FFFC421155584297FFFC4283FFE1E18C000448121883A44 +:2014E00018BFFB168405883A1421883A843FFFC4803FFE1E000004068405883A1421883A15 +:2014E800843FFFC4043FFE160005883ADFC00117DC000017DEC00204F800283AF800283A3E +:2014F0003005883AF800283A20000226208002171000131E008020741099B404108000172D +:2014F80010000926DEFFFF04DFC00015103EE83A00C0058410C0001500BFFA84DFC0001770 +:20150000DEC00104F800283A00802074109AD90400C0058410C0001500BFFA84F800283A6E +:201508002880001721400115208000152880001711000115290000150005883AF800283A93 +:20151000DEFFFB04DCC00315DC800215DC400115DC000015DFC004152027883A2823883AC7 +:201518002C00001708147980148000448440072681000217980B883A900D883A0815930084 +:201520001000042684000017003FF8060005883A000001068005883ADFC00417DCC0031714 +:20152800DC800217DC400117DC000017DEC00504F800283AF800283ADEFFFC04DC4001159D +:201530002023883A2809883A300B883A01807FC4DC000015DFC00315DC80021508155D004D +:201538001021883A100016161009883A01400304048020740813F08094993E041007883A56 +:201540009085883A108000178009883A8880001590C5883A1080011790C7883A88800115AF +:201548001880021788800215DFC00317DC800217DC400117DC000017DEC0040408157941E1 +:20155000DFC00317DC800217DC400117DC000017DEC00404F800283ADEFFFB04DC00001559 +:20155800040020742005883A84194104DC40011504400044DCC00315DC8002152827883A20 +:201560003025883A100B883A8009883A880D883ADFC0041508154B80813FFD04980B883A0F +:20156800000D883A08154B8081000304900B883A880D883ADFC00417DCC00317DC8002178B +:20157000DC400117DC000017DEC0050408154B81DEFFF504DC4002152823883A01402074B9 +:201578002959B004DD400615DD000515DCC00415DC800315DFC00A15DF000915DDC0081550 +:20158000DD800715DC0001152025883A3027883A08154400102B883A0029883A1000051E44 +:201588009009883A08157F80102B883A1000462605000044A809883A08158A401021883ABD +:20159000100044161009883A014003040813F0801007883A021000340080207410993E0405 +:20159800423FFFC418B9883A8A10703A102F883A18C00204A000062610C7883A1A000015A5 +:2015A000A880031710001A1E8005883A0000350610C7883A00802074421000341099AF0490 +:2015A8001A00001510C00017B829883A002D883A8009883A01400304D8C000150813F080B0 +:2015B000B885883AA100001710800017D8C000172080031EA08002171000010EA7001F1E11 +:2015B800B5800044A50003041DBFF12E003FE406880D883AE009883A900B883A980F883A02 +:2015C000103EE83A1023883A8005883A8800150E8009883A08157940008020741099B4041E +:2015C8001080001710000226103EE83A0000020600802074109AD9040463C83A144000153F +:2015D00000BFFFC400000706047FFB44043FFFC4003FEF061023883A003FED06047FFCC406 +:2015D800003FEB06DFC00A17DF000917DDC00817DD800717DD400617DD000517DCC00417E3 +:2015E000DC800317DC400217DC000117DEC00B04F800283A00C000841900140EDEFFFD04E8 +:2015E800DC0000150140030404002074DFC00215DC40011584193E042023883A0813F080BB +:2015F0008085883A8809883A01400304100002150813F0808085883A10000015DFC0021723 +:2015F800DC400117DC000017DEC00304F800283A000170FAF800283A00802074DEFFFA04F9 +:201600001099B204DC00001514000017DD000415DCC00315DC800215DFC00515DC40011547 +:201608002027883A1025883A05000BC484801226844002178809883A081479808887883A9C +:2016100018FFFFC71D00011E10BFFFC49887883A18C000071D0001261800051E8809883A7D +:20161800980B883A100D883A081593001000042684000017003FED060005883A00000106E9 +:201620008005883ADFC00517DD000417DCC00317DC800217DC400117DC000017DEC00604B6 +:20162800F800283ADEFFFB04DCC0031504C02074DC800215DC400115DC000015DFC0041512 +:201630002025883A0021883A9CD93E04044008048009883A014003040813F0809887883AAA +:20163800188000171000081E1C80001500C0207418D9AF04190000178005883A2400050E56 +:201640001C0000150000030684000044847FF01E00BFFA04DFC00417DCC00317DC800217D5 +:20164800DC400117DC000017DEC00504F800283A218D883A218008262080000328C000038D +:2016500010C0022610C5C83AF800283A2100004429400044003FF7060005883AF800283AE2 +:2016580073616C4672652068006573616F727265642520720000000073616C46727720688A +:20166000006574696F7272650000007273616C4665762068206669726C6961660000000018 +:2016680061766E492064696C64616572646D63200000000072204453206461656C6961667C +:20167000006572757665642F746C412F5F617265535F505561435F44415F64726F6C6176F3 +:201678006E495F6E667265745F6563610000003053206F4E6163204464206472002E7465AC +:201680004353534F0000000061766E492064696C67616D690000006561766E492064696C41 +:20168800646165680000726561766E492064696C207264680043524361766E492064696CD5 +:201690006174616443524320000000000000002D696C6156697461646420676E00617461BE +:20169800622075257365747900000000252E75252575322E0073257361647055676E697423 +:2016A0000057462061656C70772065732E74696100002E2E697265566E6979666C662067EF +:2016A8000068736172746552676E6979647075200065746161647055203F65742C593D313A +:2016B0004E3D32200000000044525355004154417365725000000073666E6F43006D72694E +:2016B8006D73694D686374616572202C007972742520732500632575252E75256B75322E53 +:2016C00025207A482E252E757A487532000000000064644F6E6576450000000000006E4F42 +:2016C8000066664F00495644494D4448000000002525752500000000702075256C65786922 +:2016D00000000073642064250000676575207746746164704B4F20650000000061656C5012 +:2016D8007220657361747365000074726E2057460000746F61647075006465747365727046 +:2016E0002D3C207320726F2000003E2D656E6F44000000005353494D20474E494D45544973 +:2016E80000000000646F4D567325203A00000000203A4F4C56207525203A4D5300007525E1 +:2016F0004353534F776620207525202E322E252E0000007574696E49727265202020726F57 +:2016F800000064252020202053204F4E00434E59343130323130322D6D20203573717261AF +:20170000000000006E616353656E696C000000736E616353656E696C727473200000002E55 +:201708006E616353656E696C0064692069726F48746E6F7A6D206C61006B73617472655610 +:201710006C61636973616D200000006B70303834206E6920706D61730072656C706D6153AC +:20171800676E696C6168702000006573506250596E6920726C6F4320006170536C616E4134 +:201720007320676F20636E790046504C65646956504C206F00000046703034326E696C2092 +:201728006972746500656C70656E694C706972746D20656C0065646F6D2058540065646F5E +:201730006D7269466572617764707520006574616576615374657320676E69740000007399 +:201738006F74754100000000484D35394828207A2056544400294949484D35334828207A1B +:201740002056544400002949484D36314528207A29565444000000007A484D3944532820C8 +:2017480000295654484D33330000007A484D30310000007A4D352E3200007A4869726F4893 +:20175000746E6F7A00006C61747265566C616369000000002056544470303834000000008D +:20175800204147567830343600303834656E654720636972393A363100000000656E65478F +:201760002063697200333A3478303233203034326974706F00002E6D783635322030343285 +:201768006974706F00002E6D4D204F4E0045444F3A31564142475220000000533A315641D6 +:2017700073475220000000423A32564162505920000072503A32564173475220000000428A +:201778003A33564142475220000056483A33564142475220000000533A3356417347522032 +:2017800000000042000000310000003200000033554E454D000000004B434142000000002B +:20178800000050554E574F44000000005446454C0000000048474952000000544F464E498F +:20179000000000005F44434C4B4341424847494C000000544B544F48003159454B544F4843 +:20179800003259454B544F48003359450000000000815C040000000100815C100000000289 +:2017A00000815C200000000300815C2C0000000400815C3C0000000500815C4C00000006CF +:2017A80000815C5C0000000700815C6C0000000800815C7C0000000900815C8C0000000ABB +:2017B00000815C980000000B00815CA80000000C00815CB80000000D00815CC00000000EBB +:2017B80000815CD000815CE000815B2000815CE800815CF800815D0800815D1800815B2039 +:2017C00000815D2400815D2C00815D3400815B2000815D3C00815D4800815CE000815D54C0 +:2017C80000815D6000815D6C00815D7C00815D8800815D9800815DA800815DB000815DBC95 +:2017D00000815DC800815DD400815DE000815DEC00815DF800815E0400815E0800815E0C8E +:2017D80000815E1000815E1800815E2000815E2400815E2C00815E3400815E3C00815E44AD +:2017E00000815E5400815E5C00815E64000000202E63655231303620000000002E636552D1 +:2017E800393037200000000000815F900000200020002CE5E926F4FD38BC2000000000004C +:2017F00000815F9C000020002000323EF113FA043B61200000000000703034324D334C5FBE +:2017F80005000030177000F0010606A8037C10C400010012703034324D334C5F03C00031E5 +:20180000177000F0010604FE035D109300020012703034324D334C5F01400032177000F016 +:20180800010601AA031F103100440011703034324D334C5F01000033177000F0010601551D +:201810000319102700480011703034320000000002D00000177000F00106035A033C1041C9 +:2018180000100012703838320000000002D000001388012001380360033C104100100012A0 +:20182000703438330000000001F000001686018001A70280033E1D320010000478303436AB +:201828000034383302800000157C018001EC032002603F3000100010693038340000000067 +:2018300002D00000176A00F0020D035A033C104100300012703038340000000002D0000039 +:20183800176A01E0020D035A063E1E3C00800014783034360030383402800000177001E0F8 +:20184000020D0320026021300100001478303436003231350280000017700200023803207C +:2018480002601C3000000010693637350000000002D000001388012002710360033C1041C3 +:2018500000300012703637350000000002D000001388024002710360063C204100000004F8 +:20185800783030380030303603200000177002580274042004801758000000107030323720 +:201860000000000005000000176A02D002EE0672052814FF00000008303832313032377884 +:2018680005000000177002D002EE0672052814DC0000001034323031383637780400000085 +:20187000177003000326054006881DA000000010303832313230317805000034177004006B +:20187800042A0698037026F800000010303830310000006907800000176A04380465089864 +:20188000052C109400300008303830310000007007800000176A043804650898052C24BCA4 +:20188800000000083032393138303178078000301770043804650898052C249400000010DF +:201890007665642F61746A2F61755F67305F7472000000007665642F6370652F6F635F71D4 +:201898006F72746E72656C6C615F305F6D5F6C7600006D657665642F6C756E2F0000006C97 +:2018A000000000000000000000000000000000000000000000000000000000000000000028 +:2018A800000000000000000000000000000000000000000000000000000000000000000020 +:2018B000000000000000000000000000000000000000000000000000000000000000000018 +:2018B800000000000000000000000000000000000000000000000000000000000000000010 +:2018C000000000000000000000000000000000000000000000000000000000000000000008 +:2018C800000000000000000000000000000000000000000000000000000000000000000000 +:2018D0000000000000000000000000000000000000000000000000000000000000000000F8 +:2018D8000000000000000000000000000000000000000000000000000000000000000000F0 +:2018E0000000000000000000000000000000000000000000000000000000000000000000E8 +:2018E8000000000000000000000000000000000000000000000000000000000000000000E0 +:2018F0000000000000000000000000000000000000000000000000000000000000000000D8 +:2018F8000000000000000000000000000000000000000000000000000000000000000000D0 +:201900000000000000000000000000000000000000000000000000000000000000000000C7 +:201908000000000000000000000000000000000000000000000000000000000000000000BF +:201910000000000000000000000000000000000000000000000000000000000000000000B7 +:201918000000000000000000000000000000000000000000000000000000000000000000AF +:201920000000000000000000000000000000000000000000000000000000000000000000A7 +:2019280000000000000000000000000000000000000000000000000000000000000000009F +:20193000000000000000000000000000000000000000000000000000000000000000000097 +:2019380000000000000000000000000000000000000000000000000000000000000000008F +:20194000000000000000000000000000000000000000000000000000000000000000000087 +:2019480000000000000000000000000000000000000000000000000000000000000000007F +:20195000000000000000000000000000000000000000000000000000000000000000000077 +:2019580000000000000000000000000000000000000000000000000000000000000000006F +:20196000000000000000000000000000000000000000000000000000000000000000000067 +:2019680000000000000000000000000000000000000000000000000000000000000000005F +:20197000000000000000000000000000000000000000000000000000000000000000000057 +:2019780000000000000000000000000000000000000000000000000000000000000000004F +:20198000000000000000000000000000000000000000000000000000000000000000000047 +:2019880000000000000000000000000000000000000000000000000000000000000000003F +:20199000000000000000000000000000000000000000000000000000000000000000000037 +:2019980000000000000000000000000000000000000000000000000000000000000000002F +:2019A000000000000000000000000000000000000000000000000000000000000000000027 +:2019A80000000000000000000000000000000000000000000000000000000000000000001F +:2019B000000000000000000000000000000000000000000000000000000000002048208807 +:2019B800200820C8200020D820C020802058204020E8201020982018017804E53CCE00817A +:2019C0003FAE03833F333D4905B80383009301B404163C493CD93F9F04163F10020E0409F9 +:2019C8003D0E00C83F6E03833ED03DAC04B2038300E9026404163C933D493F5604163E9F3C +:2019D00000000000008163A4008163AC008163B40000000000000000000000000000000047 +:2019D8000000000000000000000000000000000000000000000000000000000000000000EF +:2019E0000000000000000000000000000000000000000000000000000000000000000000E7 +:2019E8000000000000000000000000000000000000000000000000000000000000000000DF +:2019F0000000000000000000000000000000000000000000000000000000000000000000D7 +:2019F8000000000000000000000000000000000000000000000000000000000000000000CF +:201A000000000004000000000001000A000000000002000A000000000000000000000000AB +:201A08000000000000000000008159C4000000000000000000000000000000000000000020 +:201A10000000000000000000008210000000000000000000008162540000000000000000ED +:201A180000814E9400814FB000814C7800814CB400814D480000000000800000000000006F +:201A20000000000000000000000000000000000000000000000000000000000000000000A6 +:201A280000000000000000000000000000000000000000000000000000000000000000009E +:201A3000000000000000000000000000000000000000000000000000000000000000000096 +:201A380000000000000000000000000000000000000000000000000000000000000000008E +:201A400000814BE400000000008000000082140000800000000000010000008000010000BE +:201A48000000010000000000000000000000000000816240000000000000000000814B2C62 +:201A500000814B40000000000000000000000000008214A0008166780000000000000000D5 +:201A58000081667800000000000000000081667800000000000000000000000000000000B0 +:201A6000000000000000000000000000000000000000000000000000000000000000000066 +:201A680000000000000000000000000000000000000000000000000000000000000000005E +:201A7000000000000000000000000000000000000000000000000000000000000000000056 +:201A780000000000000000000000000000000000000000000000000000000000000000004E +:201A8000000000000000000000000000000000000000000000000000000000000000000046 +:201A880000000000000000000000000000000000000000000000000000000000000000003E +:201A9000000000000000000000000000000000000000000000000000000000000000000036 +:201A980000000000000000000000000000000000000000000000000000000000000000002E +:201AA000000000000000000000000000000000000000000000000000000000000000000026 +:201AA80000000000000000000000000000000000000000000000000000000000000000001E +:201AB0000000000000000000000000000000000000000000008166C0008166C00081627471 +:201AB800000000000000000000000000008153C0000000000000000000000000000000403A +:201AC000019BFCC000632EA000108010554B00800000C896008162E4FFFFFFFF008166783D +:201AC80000816678008166C8008166C800000000008166D4008166D40000000000000000CB +:201AD0000000000000000000000000000000000000000000000000000000000000000000F6 +:201AD8000000000000000000000000000000000000000000000000000000000000000000EE +:201AE0000000000000000000000000000000000000000000000000000000000000000000E6 +:201AE8000000000000000000000000000000000000000000000000000000000000000000DE +:201AF0000000000000000000000000000000000000000000000000000000000000000000D6 +:201AF8000000000000000000000000000000000000000000000000000000000000000000CE +:201B00000000000000000000000000000000000000000000000000000000000000000000C5 +:201B08000000000000000000000000000000000000000000000000000000000000000000BD +:201B10000000000000000000000000000000000000000000000000000000000000000000B5 +:201B18000000000000000000000000000000000000000000000000000000000000000000AD +:201B20000000000000000000000000000000000000000000000000000000000000000000A5 +:201B280000000000000000000000000000000000000000000000000000000000000000009D +:201B3000000000000000000000000000000000000000000000000000000000000000000095 +:201B380000000000000000000000000000000000000000000000000000000000000000008D +:201B4000000000000000000000000000000000000000000000000000000000000000000085 +:201B480000000000000000000000000000000000000000000000000000000000000000007D +:201B5000000000000000000000000000000000000000000000000000000000000000000075 +:201B580000000000000000000000000000000000000000000000000000000000000000006D +:201B6000000000000000000000000000000000000000000000000000000000000000000065 +:201B680000000000000000000000000000000000000000000000000000000000000000005D +:201B7000000000000000000000000000000000000000000000000000000000000000000055 +:201B780000000000000000000000000000000000000000000000000000000000000000004D +:201B8000000000000000000000000000000000000000000000000000000000000000000045 +:201B880000000000000000000000000000000000000000000000000000000000000000003D +:201B9000000000000000000000000000000000000000000000000000000000000000000035 +:201B980000000000000000000000000000000000000000000000000000000000000000002D +:201BA000000000000000000000000000000000000000000000000000000000000000000025 +:201BA80000000000000000000000000000000000000000000000000000000000000000001D +:201BB000000000000000000000000000000000000000000000000000000000000000000015 +:201BB80000000000000000000000000000000000000000000000000000000000000000000D +:201BC000000000000000000000000000000000000000000000000000000000000000000005 +:201BC8000000000000000000000000000000000000000000000000000000000000000000FD +:201BD0000000000000000000000000000000000000000000000000000000000000000000F5 +:201BD8000000000000000000000000000000000000000000000000000000000000000000ED +:201BE0000000000000000000000000000000000000000000000000000000000000000000E5 +:201BE8000000000000000000000000000000000000000000000000000000000000000000DD +:201BF0000000000000000000000000000000000000000000000000000000000000000000D5 +:201BF8000000000000000000000000000000000000000000000000000000000000000000CD +:201C00000000000000000000000000000000000000000000000000000000000000000000C4 +:201C08000000000000000000000000000000000000000000000000000000000000000000BC +:201C10000000000000000000000000000000000000000000000000000000000000000000B4 +:201C18000000000000000000000000000000000000000000000000000000000000000000AC +:201C20000000000000000000000000000000000000000000000000000000000000000000A4 +:201C280000000000000000000000000000000000000000000000000000000000000000009C +:201C3000000000000000000000000000000000000000000000000000000000000000000094 +:201C380000000000000000000000000000000000000000000000000000000000000000008C +:201C4000000000000000000000000000000000000000000000000000000000000000000084 +:201C480000000000000000000000000000000000000000000000000000000000000000007C +:201C5000000000000000000000000000000000000000000000000000000000000000000074 +:201C580000000000000000000000000000000000000000000000000000000000000000006C +:201C6000000000000000000000000000000000000000000000000000000000000000000064 +:201C680000000000000000000000000000000000000000000000000000000000000000005C +:201C7000000000000000000000000000000000000000000000000000000000000000000054 +:201C780000000000000000000000000000000000000000000000000000000000000000004C +:201C8000000000000000000000000000000000000000000000000000000000000000000044 +:201C880000000000000000000000000000000000000000000000000000000000000000003C +:201C9000000000000000000000000000000000000000000000000000000000000000000034 +:201C980000000000000000000000000000000000000000000000000000000000000000002C +:201CA000000000000000000000000000000000000000000000000000000000000000000024 +:201CA80000000000000000000000000000000000000000000000000000000000000000001C +:201CB000000000000000000000000000000000000000000000000000000000000000000014 +:201CB80000000000000000000000000000000000000000000000000000000000000000000C +:201CC000000000000000000000000000000000000000000000000000000000000000000004 +:201CC8000000000000000000000000000000000000000000000000000000000000000000FC +:201CD0000000000000000000000000000000000000000000000000000000000000000000F4 +:201CD8000000000000000000000000000000000000000000000000000000000000000000EC +:201CE0000000000000000000000000000000000000000000000000000000000000000000E4 +:201CE8000000000000000000000000000000000000000000000000000000000000000000DC +:201CF0000000000000000000000000000000000000000000000000000000000000000000D4 +:201CF8000000000000000000000000000000000000000000000000000000000000000000CC +:201D00000000000000000000000000000000000000000000000000000000000000000000C3 +:201D08000000000000000000000000000000000000000000000000000000000000000000BB +:201D10000000000000000000000000000000000000000000000000000000000000000000B3 +:201D18000000000000000000000000000000000000000000000000000000000000000000AB +:201D20000000000000000000000000000000000000000000000000000000000000000000A3 +:201D280000000000000000000000000000000000000000000000000000000000000000009B +:201D3000000000000000000000000000000000000000000000000000000000000000000093 +:201D380000000000000000000000000000000000000000000000000000000000000000008B +:201D4000000000000000000000000000000000000000000000000000000000000000000083 +:201D480000000000000000000000000000000000000000000000000000000000000000007B +:201D5000000000000000000000000000000000000000000000000000000000000000000073 +:201D580000000000000000000000000000000000000000000000000000000000000000006B +:201D6000000000000000000000000000000000000000000000000000000000000000000063 +:201D680000000000000000000000000000000000000000000000000000000000000000005B +:201D7000000000000000000000000000000000000000000000000000000000000000000053 +:201D780000000000000000000000000000000000000000000000000000000000000000004B +:201D8000000000000000000000000000000000000000000000000000000000000000000043 +:201D880000000000000000000000000000000000000000000000000000000000000000003B +:201D9000000000000000000000000000000000000000000000000000000000000000000033 +:201D980000000000000000000000000000000000000000000000000000000000000000002B +:201DA000000000000000000000000000000000000000000000000000000000000000000023 +:201DA80000000000000000000000000000000000000000000000000000000000000000001B +:201DB000000000000000000000000000000000000000000000000000000000000000000013 +:201DB80000000000000000000000000000000000000000000000000000000000000000000B +:201DC000000000000000000000000000000000000000000000000000000000000000000003 +:201DC8000000000000000000000000000000000000000000000000000000000000000000FB +:201DD0000000000000000000000000000000000000000000000000000000000000000000F3 +:201DD8000000000000000000000000000000000000000000000000000000000000000000EB +:201DE0000000000000000000000000000000000000000000000000000000000000000000E3 +:201DE8000000000000000000000000000000000000000000000000000000000000000000DB +:201DF0000000000000000000000000000000000000000000000000000000000000000000D3 +:201DF8000000000000000000000000000000000000000000000000000000000000000000CB +:201E00000000000000000000000000000000000000000000000000000000000000000000C2 +:201E08000000000000000000000000000000000000000000000000000000000000000000BA +:201E10000000000000000000000000000000000000000000000000000000000000000000B2 +:201E18000000000000000000000000000000000000000000000000000000000000000000AA +:201E20000000000000000000000000000000000000000000000000000000000000000000A2 +:201E280000000000000000000000000000000000000000000000000000000000000000009A +:201E3000000000000000000000000000000000000000000000000000000000000000000092 +:201E380000000000000000000000000000000000000000000000000000000000000000008A +:201E4000000000000000000000000000000000000000000000000000000000000000000082 +:201E480000000000000000000000000000000000000000000000000000000000000000007A +:201E5000000000000000000000000000000000000000000000000000000000000000000072 +:201E580000000000000000000000000000000000000000000000000000000000000000006A +:201E6000000000000000000000000000000000000000000000000000000000000000000062 +:201E680000000000000000000000000000000000000000000000000000000000000000005A +:201E7000000000000000000000000000000000000000000000000000000000000000000052 +:201E780000000000000000000000000000000000000000000000000000000000000000004A +:201E8000000000000000000000000000000000000000000000000000000000000000000042 +:201E880000000000000000000000000000000000000000000000000000000000000000003A +:201E9000000000000000000000000000000000000000000000000000000000000000000032 +:201E980000000000000000000000000000000000000000000000000000000000000000002A +:201EA000000000000000000000000000000000000000000000000000000000000000000022 +:201EA80000000000000000000000000000000000000000000000000000000000000000001A +:201EB000000000000000000000000000000000000000000000000000000000000000000012 +:201EB80000000000000000000000000000000000000000000000000000000000000000000A +:201EC000000000000000000000000000000000000000000000000000000000000000000002 +:201EC8000000000000000000000000000000000000000000000000000000000000000000FA +:201ED0000000000000000000000000000000000000000000000000000000000000000000F2 +:201ED8000000000000000000000000000000000000000000000000000000000000000000EA +:201EE0000000000000000000000000000000000000000000000000000000000000000000E2 +:201EE8000000000000000000000000000000000000000000000000000000000000000000DA +:201EF0000000000000000000000000000000000000000000000000000000000000000000D2 +:201EF8000000000000000000000000000000000000000000000000000000000000000000CA +:201F00000000000000000000000000000000000000000000000000000000000000000000C1 +:201F08000000000000000000000000000000000000000000000000000000000000000000B9 +:201F10000000000000000000000000000000000000000000000000000000000000000000B1 +:201F18000000000000000000000000000000000000000000000000000000000000000000A9 +:201F20000000000000000000000000000000000000000000000000000000000000000000A1 +:201F2800000000000000000000000000000000000000000000000000000000000000000099 +:201F3000000000000000000000000000000000000000000000000000000000000000000091 +:201F3800000000000000000000000000000000000000000000000000000000000000000089 +:201F4000000000000000000000000000000000000000000000000000000000000000000081 +:201F4800000000000000000000000000000000000000000000000000000000000000000079 +:201F5000000000000000000000000000000000000000000000000000000000000000000071 +:201F5800000000000000000000000000000000000000000000000000000000000000000069 +:201F6000000000000000000000000000000000000000000000000000000000000000000061 +:201F6800000000000000000000000000000000000000000000000000000000000000000059 +:201F7000000000000000000000000000000000000000000000000000000000000000000051 +:201F7800000000000000000000000000000000000000000000000000000000000000000049 +:201F8000000000000000000000000000000000000000000000000000000000000000000041 +:201F8800000000000000000000000000000000000000000000000000000000000000000039 +:201F9000000000000000000000000000000000000000000000000000000000000000000031 +:201F9800000000000000000000000000000000000000000000000000000000000000000029 +:201FA000000000000000000000000000000000000000000000000000000000000000000021 +:201FA800000000000000000000000000000000000000000000000000000000000000000019 +:201FB000000000000000000000000000000000000000000000000000000000000000000011 +:201FB800000000000000000000000000000000000000000000000000000000000000000009 +:201FC000000000000000000000000000000000000000000000000000000000000000000001 +:201FC8000000000000000000000000000000000000000000000000000000000000000000F9 +:201FD0000000000000000000000000000000000000000000000000000000000000000000F1 +:201FD8000000000000000000000000000000000000000000000000000000000000000000E9 +:201FE0000000000000000000000000000000000000000000000000000000000000000000E1 +:201FE8000000000000000000000000000000000000000000000000000000000000000000D9 +:201FF0000000000000000000000000000000000000000000000000000000000000000000D1 +:201FF8000000000000000000000000000000000000000000000000000000000000000000C9 +:202000000000000000000000000000000000000000000000000000000000000000000000C0 +:202008000000000000000000000000000000000000000000000000000000000000000000B8 +:202010000000000000000000000000000000000000000000000000000000000000000000B0 +:202018000000000000000000000000000000000000000000000000000000000000000000A8 +:202020000000000000000000000000000000000000000000000000000000000000000000A0 +:20202800000000000000000000000000000000000000000000000000000000000000000098 +:20203000000000000000000000000000000000000000000000000000000000000000000090 +:20203800000000000000000000000000000000000000000000000000000000000000000088 +:20204000000000000000000000000000000000000000000000000000000000000000000080 +:20204800000000000000000000000000000000000000000000000000000000000000000078 +:20205000000000000000000000000000000000000000000000000000000000000000000070 +:20205800000000000000000000000000000000000000000000000000000000000000000068 +:20206000000000000000000000000000000000000000000000000000000000000000000060 +:20206800000000000000000000000000000000000000000000000000000000000000000058 +:20207000000000000000000000000000000000000000000000000000000000000000000050 +:20207800000000000000000000000000000000000000000000000000000000000000000048 +:20208000000000000000000000000000000000000000000000000000000000000000000040 +:20208800000000000000000000000000000000000000000000000000000000000000000038 +:20209000000000000000000000000000000000000000000000000000000000000000000030 +:20209800000000000000000000000000000000000000000000000000000000000000000028 +:2020A000000000000000000000000000000000000000000000000000000000000000000020 +:2020A800000000000000000000000000000000000000000000000000000000000000000018 +:2020B000000000000000000000000000000000000000000000000000000000000000000010 +:2020B800000000000000000000000000000000000000000000000000000000000000000008 +:2020C000000000000000000000000000000000000000000000000000000000000000000000 +:2020C8000000000000000000000000000000000000000000000000000000000000000000F8 +:2020D0000000000000000000000000000000000000000000000000000000000000000000F0 +:2020D8000000000000000000000000000000000000000000000000000000000000000000E8 +:2020E0000000000000000000000000000000000000000000000000000000000000000000E0 +:2020E8000000000000000000000000000000000000000000000000000000000000000000D8 +:2020F0000000000000000000000000000000000000000000000000000000000000000000D0 +:2020F8000000000000000000000000000000000000000000000000000000000000000000C8 +:202100000000000000000000000000000000000000000000000000000000000000000000BF +:202108000000000000000000000000000000000000000000000000000000000000000000B7 +:202110000000000000000000000000000000000000000000000000000000000000000000AF +:202118000000000000000000000000000000000000000000000000000000000000000000A7 +:2021200000000000000000000000000000000000000000000000000000000000000000009F +:20212800000000000000000000000000000000000000000000000000000000000000000097 +:2021300000000000000000000000000000000000000000000000000000000000000000008F +:20213800000000000000000000000000000000000000000000000000000000000000000087 +:2021400000000000000000000000000000000000000000000000000000000000000000007F +:20214800000000000000000000000000000000000000000000000000000000000000000077 +:2021500000000000000000000000000000000000000000000000000000000000000000006F +:20215800000000000000000000000000000000000000000000000000000000000000000067 +:2021600000000000000000000000000000000000000000000000000000000000000000005F +:20216800000000000000000000000000000000000000000000000000000000000000000057 +:2021700000000000000000000000000000000000000000000000000000000000000000004F +:20217800000000000000000000000000000000000000000000000000000000000000000047 +:2021800000000000000000000000000000000000000000000000000000000000000000003F +:20218800000000000000000000000000000000000000000000000000000000000000000037 +:2021900000000000000000000000000000000000000000000000000000000000000000002F +:20219800000000000000000000000000000000000000000000000000000000000000000027 +:2021A00000000000000000000000000000000000000000000000000000000000000000001F +:2021A800000000000000000000000000000000000000000000000000000000000000000017 +:2021B00000000000000000000000000000000000000000000000000000000000000000000F +:2021B800000000000000000000000000000000000000000000000000000000000000000007 +:2021C0000000000000000000000000000000000000000000000000000000000000000000FF +:2021C8000000000000000000000000000000000000000000000000000000000000000000F7 +:2021D0000000000000000000000000000000000000000000000000000000000000000000EF +:2021D8000000000000000000000000000000000000000000000000000000000000000000E7 +:2021E0000000000000000000000000000000000000000000000000000000000000000000DF +:2021E8000000000000000000000000000000000000000000000000000000000000000000D7 +:2021F0000000000000000000000000000000000000000000000000000000000000000000CF +:2021F8000000000000000000000000000000000000000000000000000000000000000000C7 +:202200000000000000000000000000000000000000000000000000000000000000000000BE +:202208000000000000000000000000000000000000000000000000000000000000000000B6 +:202210000000000000000000000000000000000000000000000000000000000000000000AE +:202218000000000000000000000000000000000000000000000000000000000000000000A6 +:2022200000000000000000000000000000000000000000000000000000000000000000009E +:20222800000000000000000000000000000000000000000000000000000000000000000096 +:2022300000000000000000000000000000000000000000000000000000000000000000008E +:20223800000000000000000000000000000000000000000000000000000000000000000086 +:2022400000000000000000000000000000000000000000000000000000000000000000007E +:20224800000000000000000000000000000000000000000000000000000000000000000076 +:2022500000000000000000000000000000000000000000000000000000000000000000006E +:20225800000000000000000000000000000000000000000000000000000000000000000066 +:2022600000000000000000000000000000000000000000000000000000000000000000005E +:20226800000000000000000000000000000000000000000000000000000000000000000056 +:2022700000000000000000000000000000000000000000000000000000000000000000004E +:20227800000000000000000000000000000000000000000000000000000000000000000046 +:2022800000000000000000000000000000000000000000000000000000000000000000003E +:20228800000000000000000000000000000000000000000000000000000000000000000036 +:2022900000000000000000000000000000000000000000000000000000000000000000002E +:20229800000000000000000000000000000000000000000000000000000000000000000026 +:2022A00000000000000000000000000000000000000000000000000000000000000000001E +:2022A800000000000000000000000000000000000000000000000000000000000000000016 +:2022B00000000000000000000000000000000000000000000000000000000000000000000E +:2022B800000000000000000000000000000000000000000000000000000000000000000006 +:2022C0000000000000000000000000000000000000000000000000000000000000000000FE +:2022C8000000000000000000000000000000000000000000000000000000000000000000F6 +:2022D0000000000000000000000000000000000000000000000000000000000000000000EE +:2022D8000000000000000000000000000000000000000000000000000000000000000000E6 +:2022E0000000000000000000000000000000000000000000000000000000000000000000DE +:2022E8000000000000000000000000000000000000000000000000000000000000000000D6 +:2022F0000000000000000000000000000000000000000000000000000000000000000000CE +:2022F8000000000000000000000000000000000000000000000000000000000000000000C6 +:202300000000000000000000000000000000000000000000000000000000000000000000BD +:202308000000000000000000000000000000000000000000000000000000000000000000B5 +:202310000000000000000000000000000000000000000000000000000000000000000000AD +:202318000000000000000000000000000000000000000000000000000000000000000000A5 +:2023200000000000000000000000000000000000000000000000000000000000000000009D +:20232800000000000000000000000000000000000000000000000000000000000000000095 +:2023300000000000000000000000000000000000000000000000000000000000000000008D +:20233800000000000000000000000000000000000000000000000000000000000000000085 +:2023400000000000000000000000000000000000000000000000000000000000000000007D +:20234800000000000000000000000000000000000000000000000000000000000000000075 +:2023500000000000000000000000000000000000000000000000000000000000000000006D +:20235800000000000000000000000000000000000000000000000000000000000000000065 +:2023600000000000000000000000000000000000000000000000000000000000000000005D +:20236800000000000000000000000000000000000000000000000000000000000000000055 +:2023700000000000000000000000000000000000000000000000000000000000000000004D +:20237800000000000000000000000000000000000000000000000000000000000000000045 +:2023800000000000000000000000000000000000000000000000000000000000000000003D +:20238800000000000000000000000000000000000000000000000000000000000000000035 +:2023900000000000000000000000000000000000000000000000000000000000000000002D +:20239800000000000000000000000000000000000000000000000000000000000000000025 +:2023A00000000000000000000000000000000000000000000000000000000000000000001D +:2023A800000000000000000000000000000000000000000000000000000000000000000015 +:2023B00000000000000000000000000000000000000000000000000000000000000000000D +:2023B800000000000000000000000000000000000000000000000000000000000000000005 +:2023C0000000000000000000000000000000000000000000000000000000000000000000FD +:2023C8000000000000000000000000000000000000000000000000000000000000000000F5 +:2023D0000000000000000000000000000000000000000000000000000000000000000000ED +:2023D8000000000000000000000000000000000000000000000000000000000000000000E5 +:2023E0000000000000000000000000000000000000000000000000000000000000000000DD +:2023E8000000000000000000000000000000000000000000000000000000000000000000D5 +:2023F0000000000000000000000000000000000000000000000000000000000000000000CD +:2023F8000000000000000000000000000000000000000000000000000000000000000000C5 +:00000001FF diff --git a/software/sys_controller/spi_charlcd/lcd.c b/software/sys_controller/spi_charlcd/lcd.c new file mode 100644 index 0000000..33c6961 --- /dev/null +++ b/software/sys_controller/spi_charlcd/lcd.c @@ -0,0 +1,108 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "lcd.h" +#include "alt_types.h" +#include "altera_avalon_pio_regs.h" + +#define LCD_CMD 0x00 +#define LCD_DATA 0x40 + +#define WRDELAY 20 +#define CLEARDELAY 800 + +void lcd_init() { + alt_u8 lcd_ctrl = 0x00; + IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); + usleep(WRDELAY); + + SPI_write(I2CA_BASE, 0x38); // function set + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x39); // function set, select extended table (IS=1) + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x14); // osc freq + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x71); // contrast set + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x5E); // power/icon/cont + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x6D); // follower control + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x0C); // display on + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x01); // clear display + usleep(CLEARDELAY); + SPI_write(I2CA_BASE, 0x06); // entry mode set + usleep(WRDELAY); + SPI_write(I2CA_BASE, 0x02); // return home + usleep(CLEARDELAY); + + lcd_ctrl |= LCD_CS_N; + IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); +} + +void lcd_write(char *row1, char *row2) { + alt_u8 i, rowlen; + alt_u8 lcd_ctrl = 0x00; + + IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); + + SPI_write(I2CA_BASE, 0x01); // clear display + usleep(CLEARDELAY); + + // Set RS to enter data write mode + lcd_ctrl |= LCD_RS; + IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, lcd_ctrl); + + //ensure no empty row + rowlen = strnlen(row1, LCD_ROW_LEN); + if (rowlen == 0) { + strncpy(row1, " ", LCD_ROW_LEN+1); + rowlen++; + } + + for (i=0; i +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef LCD_H_ +#define LCD_H_ + +#include "system.h" +#include +#include "sysconfig.h" + +#define LCD_ROW_LEN 16 + +//#define I2C_DEBUG +#define I2CA_BASE I2C_OPENCORES_0_BASE + +#define LCD_CS_N (1<<0) +#define LCD_RS (1<<1) + +void lcd_init(); + +void lcd_write(char *row1, char *row2); + +#endif /* LCD_H_ */ diff --git a/software/sys_controller/sysconfig.h b/software/sys_controller/sysconfig.h new file mode 100644 index 0000000..d24dbad --- /dev/null +++ b/software/sys_controller/sysconfig.h @@ -0,0 +1,34 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef SYSCONFIG_H_ +#define SYSCONFIG_H_ + +#ifndef DEBUG +#define OS_PRINTF(...) +#define ErrorF(...) +#define printf(...) +#else +#define OS_PRINTF printf +#define ErrorF printf +// use reduced printf +//#define printf alt_printf +#endif + +#endif /* SYSCONFIG_H_ */ diff --git a/software/sys_controller/ths7353/ths7353.c b/software/sys_controller/ths7353/ths7353.c new file mode 100644 index 0000000..a2af36b --- /dev/null +++ b/software/sys_controller/ths7353/ths7353.c @@ -0,0 +1,81 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include "system.h" +#include "altera_avalon_pio_regs.h" +#include "i2c_opencores.h" +#include "ths7353.h" + +inline alt_u32 ths_readreg(alt_u8 channel) { + //Phase 1 + I2C_start(I2CA_BASE, THS_BASE, 0); + I2C_write(I2CA_BASE, channel, 1); + + //Phase 2 + I2C_start(I2CA_BASE, THS_BASE, 1); + return I2C_read(I2CA_BASE,1); +} + +inline void ths_writereg(alt_u8 channel, alt_u8 data) { + I2C_start(I2CA_BASE, THS_BASE, 0); + I2C_write(I2CA_BASE, channel, 0); + I2C_write(I2CA_BASE, data, 1); +} + +int ths_init() { + //Avoid random FIFO state (see datasheet p.37) + I2C_write(I2CA_BASE, 0x00, 0); + usleep(10); + + //Initialize all channels + ths_writereg(THS_CH1, (THS_LPF_DEFAULT< +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef THS7353_H_ +#define THS7353_H_ + +#include "sysconfig.h" + +#define THS_BASE (0x58>>1) + +#define THS_CH1 0x01 +#define THS_CH2 0x02 +#define THS_CH3 0x03 + +typedef enum { + THS_INPUT_A = 0, + THS_INPUT_B = 1, + THS_STANDBY = 2 +} ths_input_t; + +#define THS_LPF_DEFAULT 0x3 +#define THS_LPF_MASK 0x18 +#define THS_LPF_OFFS 3 + +#define THS_SRC_MASK 0x20 +#define THS_SRC_OFFS 5 + +#define THS_MODE_MASK 0x7 +#define THS_MODE_OFFS 0 + +#define THS_MODE_DISABLE 0 +#define THS_MODE_AVMUTE 1 +#define THS_MODE_AC_BIAS 4 +#define THS_MODE_STC 6 //mid bias + +#define THS_LPF_BYPASS 0x03 + +//#define I2C_DEBUG +#define I2CA_BASE I2C_OPENCORES_0_BASE + +int ths_init(); + +void ths_set_lpf(alt_u8 val); + +void ths_source_sel(ths_input_t input, alt_u8 lpf); + +#endif /* THS7353_H_ */ diff --git a/software/sys_controller/tvp7002/tvp7002.c b/software/sys_controller/tvp7002/tvp7002.c new file mode 100644 index 0000000..98f0234 --- /dev/null +++ b/software/sys_controller/tvp7002/tvp7002.c @@ -0,0 +1,401 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include "system.h" +#include "altera_avalon_pio_regs.h" +#include "i2c_opencores.h" +#include "tvp7002.h" + +//#define SYNCBYPASS // Bypass VGA syncs (for debug - needed for interlace?) +//#define EXTADCCLK // Use external ADC clock (external osc) +//#define ADCPOWERDOWN // Power-down ADCs +//#define PLLPOSTDIV // Double-rate PLL with div-by-2 (decrease jitter?) + +/* Y'Pb'Pr' to R'G'B' CSC coefficients. + * + * Coefficients from "Colour Space Conversions" (http://www.poynton.com/PDFs/coloureq.pdf). + */ +const ypbpr_to_rgb_csc_t csc_coeffs[] = { + { "Rec. 601", 0x2000, 0x0000, 0x2CE5, 0x2000, 0xF4FD, 0xE926, 0x2000, 0x38BC, 0x0000 }, // eq. 101 + { "Rec. 709", 0x2000, 0x0000, 0x323E, 0x2000, 0xFA04, 0xF113, 0x2000, 0x3B61, 0x0000 }, // eq. 105 +}; + +extern mode_data_t video_modes[]; + +static inline void tvp_set_hpllcoast(alt_u8 pre, alt_u8 post) { + tvp_writereg(TVP_HPLLPRECOAST, pre); + tvp_writereg(TVP_HPLLPOSTCOAST, post); +} + +static inline void tvp_set_ssthold(alt_u8 vsdetect_thold) { + tvp_writereg(TVP_SSTHOLD, vsdetect_thold); +} + +static void tvp_set_clamp(video_format fmt) { + switch (fmt) { + case FORMAT_RGBS: + case FORMAT_RGBHV: + case FORMAT_RGsB: + //select bottom clamp (RGB) + tvp_writereg(TVP_SOGTHOLD, 0x58); + break; + case FORMAT_YPbPr: + //select mid clamp for Pb & Pr + tvp_writereg(TVP_SOGTHOLD, 0x5D); + break; + default: + break; + } +} + +static void tvp_set_clamp_position(video_type type) { + switch (type) { + case VIDEO_LDTV: + tvp_writereg(TVP_CLAMPSTART, 0x2); + tvp_writereg(TVP_CLAMPWIDTH, 0x6); + break; + case VIDEO_SDTV: + case VIDEO_EDTV: + case VIDEO_PC: + tvp_writereg(TVP_CLAMPSTART, 0x6); + tvp_writereg(TVP_CLAMPWIDTH, 0x10); + break; + case VIDEO_HDTV: + tvp_writereg(TVP_CLAMPSTART, 0x32); + tvp_writereg(TVP_CLAMPWIDTH, 0x20); + break; + default: + break; + } +} + +static void tvp_set_alc(video_type type) { + //disable ALC + //tvp_writereg(TVP_ALCEN, 0x00); + //tvp_writereg(TVP_ALCEN, 0x80); + + //set analog (coarse) gain to max recommended value (-> 91% of the ADC range with 0.7Vpp input) + tvp_writereg(TVP_BG_CGAIN, 0x88); + tvp_writereg(TVP_R_CGAIN, 0x08); + + //set rest of the gain digitally (fine) to utilize 100% of the range at the output (0.91*(1+(26/256)) = 1) + tvp_writereg(TVP_R_FGAIN, 26); + tvp_writereg(TVP_G_FGAIN, 26); + tvp_writereg(TVP_B_FGAIN, 26); + + //select ALC placement + switch (type) { + case VIDEO_LDTV: + tvp_writereg(TVP_ALCPLACE, 0x9); + break; + case VIDEO_SDTV: + case VIDEO_EDTV: + case VIDEO_PC: + tvp_writereg(TVP_ALCPLACE, 0x18); + break; + case VIDEO_HDTV: + tvp_writereg(TVP_ALCPLACE, 0x5A); + break; + default: + break; + } +} + + +inline alt_u32 tvp_readreg(alt_u32 regaddr) { + I2C_start(I2CA_BASE, TVP_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 1); //don't use repeated start as it seems unreliable at 400kHz + I2C_start(I2CA_BASE, TVP_BASE, 1); + return I2C_read(I2CA_BASE,1); +} + +inline void tvp_writereg(alt_u32 regaddr, alt_u8 data) { + I2C_start(I2CA_BASE, TVP_BASE, 0); + I2C_write(I2CA_BASE, regaddr, 0); + I2C_write(I2CA_BASE, data, 1); +} + +inline void tvp_reset() { + usleep(10000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00); + usleep(10000); + IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01); + usleep(10000); +} + +inline void tvp_disable_output() { + usleep(10000); + tvp_writereg(TVP_MISCCTRL1, 0x13); + usleep(10000); + tvp_writereg(TVP_MISCCTRL2, 0x03); + usleep(10000); +} + +inline void tvp_enable_output() { + usleep(10000); + tvp_writereg(TVP_MISCCTRL1, 0x11); + usleep(10000); + tvp_writereg(TVP_MISCCTRL2, 0x02); + usleep(10000); +} + +void tvp_init() { + // disable output + tvp_disable_output(); + + //Set global defaults + + // Hsync input->output delay (horizontal shift) + // Default is 13, which maintains alignment of RGB and hsync at output + //tvp_writereg(TVP_HSOUTSTART, 0); + + // Hsync edge->Vsync edge delay + tvp_writereg(TVP_VSOUTALIGN, 0); + + // Set default CSC coeffs. + tvp_sel_csc(&csc_coeffs[0]); + + // Set default phase + tvp_set_hpll_phase(0x10); + + // Set min LPF + tvp_set_lpf(0); + tvp_set_sync_lpf(0); + + // Increase line length tolerance + tvp_writereg(TVP_LINELENTOL, 0x06); + + // Common sync separator threshold + // Some arcade games need more that the default 0x40 + tvp_set_ssthold(0x44); +} + +// Configure H-PLL (sampling rate, VCO gain and charge pump current) +void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2) { + alt_u32 pclk_est; + alt_u8 vco_range; + alt_u8 cp_current; + + alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0xF8; + + // Enable PLL post-div-by-2 with double samplerate + if (plldivby2) { + tvp_writereg(TVP_HPLLPHASE, status|1); + h_samplerate = 2*h_samplerate; + } else { + tvp_writereg(TVP_HPLLPHASE, status); + } + + tvp_writereg(TVP_HPLLDIV_MSB, (h_samplerate >> 4)); + tvp_writereg(TVP_HPLLDIV_LSB, ((h_samplerate & 0xf) << 4)); + + printf("Horizontal samplerate set to %u\n", h_samplerate); + + pclk_est = ((alt_u32)h_samplerate * v_lines * hz) / 1000; //in kHz + + printf("Estimated PCLK: %u.%.3u MHz\n", pclk_est/1000, pclk_est%1000); + + if (pclk_est < 36000) { + vco_range = 0; + } else if (pclk_est < 70000) { + vco_range = 1; + } else if (pclk_est < 135000) { + vco_range = 2; + } else { + vco_range = 3; + } + + cp_current = (40*Kvco[vco_range]+h_samplerate/2) / h_samplerate; //"+h_samplerate/2" for fast rounding + + printf("VCO range: %s\nCPC: %u\n", Kvco_str[vco_range], cp_current); + tvp_writereg(TVP_HPLLCTRL, ((vco_range << 6) | (cp_current << 3))); +} + +void tvp_sel_clk(alt_u8 refclk) { + alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0xFA; + + //TODO: set SOG and CLP LPF based on mode + if (refclk == REFCLK_INTCLK) { + tvp_writereg(TVP_INPMUX2, status|0x2); + } else { +#ifdef EXTADCCLK + tvp_writereg(TVP_INPMUX2, status|0x8); +#else + tvp_writereg(TVP_INPMUX2, status|0xA); +#endif + } +} + +void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc) { + tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8)); + tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff)); + tvp_writereg(TVP_CSC2HI, (csc->G_Pb >> 8)); + tvp_writereg(TVP_CSC2LO, (csc->G_Pb & 0xff)); + tvp_writereg(TVP_CSC3HI, (csc->G_Pr >> 8)); + tvp_writereg(TVP_CSC3LO, (csc->G_Pr & 0xff)); + + tvp_writereg(TVP_CSC4HI, (csc->R_Y >> 8)); + tvp_writereg(TVP_CSC4LO, (csc->R_Y & 0xff)); + tvp_writereg(TVP_CSC5HI, (csc->R_Pb >> 8)); + tvp_writereg(TVP_CSC5LO, (csc->R_Pb & 0xff)); + tvp_writereg(TVP_CSC6HI, (csc->R_Pr >> 8)); + tvp_writereg(TVP_CSC6LO, (csc->R_Pr & 0xff)); + + tvp_writereg(TVP_CSC7HI, (csc->B_Y >> 8)); + tvp_writereg(TVP_CSC7LO, (csc->B_Y & 0xff)); + tvp_writereg(TVP_CSC8HI, (csc->B_Pb >> 8)); + tvp_writereg(TVP_CSC8LO, (csc->B_Pb & 0xff)); + tvp_writereg(TVP_CSC9HI, (csc->B_Pr >> 8)); + tvp_writereg(TVP_CSC9LO, (csc->B_Pr & 0xff)); +} + +void tvp_set_lpf(alt_u8 val) { + alt_u8 status = tvp_readreg(TVP_VIDEOBWLIM) & 0xF0; + tvp_writereg(TVP_VIDEOBWLIM, status|val); + printf("TVP LPF value set to 0x%x\n", val); +} + +void tvp_set_sync_lpf(alt_u8 val) { + alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0x3F; + tvp_writereg(TVP_INPMUX2, status|((3-val)<<6)); + printf("Sync LPF value set to 0x%x\n", (3-val)); +} + +void tvp_set_hpll_phase(alt_u8 val) { + alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0x07; + tvp_writereg(TVP_HPLLPHASE, (val<<3)|status); + printf("Phase value set to 0x%x\n", val); +} + +void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk) { + // Configure clock settings + tvp_sel_clk(refclk); + + // Clamp position and ALC + tvp_set_clamp_position(type); + tvp_set_alc(type); + + // Macrovision enable/disable, coast disable for RGBHV. + // Coast needs to be enabled when HSYNC is missing during VSYNC. Valid only for RGBHV? + // Macrovision should be enabled when serration pulses etc. present, so disable only for RGBHV. + switch (type) { + case VIDEO_PC: + //tvp_writereg(TVP_MISCCTRL4, 0x04); + tvp_writereg(TVP_MISCCTRL4, 0x0C); + tvp_writereg(TVP_MVSWIDTH, 0x03); + break; + case VIDEO_HDTV: + tvp_writereg(TVP_MISCCTRL4, 0x08); + tvp_writereg(TVP_MVSWIDTH, 0x0E); + break; + case VIDEO_LDTV: + case VIDEO_SDTV: + case VIDEO_EDTV: + tvp_writereg(TVP_MISCCTRL4, 0x08); + tvp_writereg(TVP_MVSWIDTH, 0x88); // TODO: check mode + break; + default: + break; + } + + tvp_setup_hpll(video_modes[modeid].h_total, vlines, hz, !!(video_modes[modeid].flags & MODE_PLLDIVBY2)); + + //Long coast may lead to PLL frequency drift and sync loss (e.g. SNES) + /*if (video_modes[modeid].v_active < 720) + tvp_set_hpllcoast(3, 3); + else*/ + tvp_set_hpllcoast(1, 0); + + // Hsync output width + tvp_writereg(TVP_HSOUTWIDTH, video_modes[modeid].h_synclen); +} + +void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk) { + alt_u8 sync_status; + alt_u8 sog_ch; + + if ((fmt == FORMAT_RGsB) || (fmt == FORMAT_YPbPr)) + sog_ch = (input == TVP_INPUT3) ? 2 : 0; + else if ((input == TVP_INPUT1) && (fmt == FORMAT_RGBS)) + sog_ch = 1; + else + sog_ch = 2; + + // RGB+SOG input select + tvp_writereg(TVP_INPMUX1, (sog_ch<<6) | (input<<4) | (input<<2) | input); + + // Configure clock settings + tvp_sel_clk(refclk); + + // Clamp setup + tvp_set_clamp(fmt); + + // HV/SOG sync select + if ((input == TVP_INPUT3) && (fmt != FORMAT_RGsB)) { + if (fmt == FORMAT_RGBHV) + tvp_writereg(TVP_SYNCCTRL1, 0x52); + else // RGBS + tvp_writereg(TVP_SYNCCTRL1, 0x53); + + sync_status = tvp_readreg(TVP_SYNCSTAT); + if (sync_status & (1<<7)) + printf("%s detected, %s polarity\n", (sync_status & (1<<3)) ? "Csync" : "Hsync", (sync_status & (1<<5)) ? "pos" : "neg"); + if (sync_status & (1<<4)) + printf("Vsync detected, %s polarity\n", (sync_status & (1<<2)) ? "pos" : "neg"); + } else { + tvp_writereg(TVP_SYNCCTRL1, 0x5B); + sync_status = tvp_readreg(TVP_SYNCSTAT); + if (sync_status & (1<<1)) + printf("SOG detected\n"); + else + printf("SOG not detected\n"); + } + + // Enable CSC for YPbPr + if (fmt == FORMAT_YPbPr) + tvp_writereg(TVP_MISCCTRL3, 0x10); + else + tvp_writereg(TVP_MISCCTRL3, 0x00); + + #ifdef SYNCBYPASS + tvp_writereg(TVP_SYNCBYPASS, 0x03); + #else + tvp_writereg(TVP_SYNCBYPASS, 0x00); + #endif + + //TODO: + //clamps + //TVP_ADCSETUP + + printf("\n"); +} + +alt_u8 tvp_check_sync(tvp_input_t input) { + alt_u8 sync_status; + + sync_status = tvp_readreg(TVP_SYNCSTAT); + + if (input == TVP_INPUT3) + return !!((sync_status & 0x98) > 0x80); + //return !!((sync_status & 0x90) == 0x90); + else + return !!(sync_status & (1<<1)); +} diff --git a/software/sys_controller/tvp7002/tvp7002.h b/software/sys_controller/tvp7002/tvp7002.h new file mode 100644 index 0000000..1453cd6 --- /dev/null +++ b/software/sys_controller/tvp7002/tvp7002.h @@ -0,0 +1,90 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef TVP7002_H_ +#define TVP7002_H_ + +#include "tvp7002_regs.h" +#include "video_modes.h" +#include "sysconfig.h" + +//#define I2C_DEBUG +#define I2CA_BASE I2C_OPENCORES_0_BASE + +typedef enum { + TVP_INPUT1 = 0, + TVP_INPUT2 = 1, + TVP_INPUT3 = 2 +} tvp_input_t; + +static const alt_u8 Kvco[] = {75, 85, 150, 200}; +static const char *Kvco_str[] = { "Ultra low", "Low", "Medium", "High" }; + +typedef enum { + REFCLK_EXT27 = 0, + REFCLK_INTCLK = 1 +} tvp_refclk_t; + +typedef struct { + const char *name; + alt_u16 R_Y; + alt_u16 R_Pb; + alt_u16 R_Pr; + alt_u16 G_Y; + alt_u16 G_Pb; + alt_u16 G_Pr; + alt_u16 B_Y; + alt_u16 B_Pb; + alt_u16 B_Pr; +} ypbpr_to_rgb_csc_t; + +static const alt_u32 clkrate[] = {27000000, 6500000}; //in MHz + + +inline alt_u32 tvp_readreg(alt_u32 regaddr); + +inline void tvp_writereg(alt_u32 regaddr, alt_u8 data); + +inline void tvp_reset(); + +inline void tvp_disable_output(); + +inline void tvp_enable_output(); + +void tvp_init(); + +void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2); + +void tvp_sel_clk(alt_u8 refclk); + +void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc); + +void tvp_set_lpf(alt_u8 val); + +void tvp_set_sync_lpf(alt_u8 val); + +void tvp_set_hpll_phase(alt_u8 val); + +void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk); + +void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk); + +alt_u8 tvp_check_sync(tvp_input_t input); + +#endif /* TVP7002_H_ */ diff --git a/software/sys_controller/tvp7002/tvp7002_regs.h b/software/sys_controller/tvp7002/tvp7002_regs.h new file mode 100644 index 0000000..99b52c3 --- /dev/null +++ b/software/sys_controller/tvp7002/tvp7002_regs.h @@ -0,0 +1,117 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef TVP7002_REGS_H_ +#define TVP7002_REGS_H_ + +#define TVP_BASE (0xB8>>1) + +#define TVP_CHIPREV 0x00 +#define TVP_HPLLDIV_MSB 0x01 +#define TVP_HPLLDIV_LSB 0x02 +#define TVP_HPLLCTRL 0x03 +#define TVP_HPLLPHASE 0x04 +#define TVP_CLAMPSTART 0x05 +#define TVP_CLAMPWIDTH 0x06 +#define TVP_HSOUTWIDTH 0x07 +#define TVP_B_FGAIN 0x08 +#define TVP_G_FGAIN 0x09 +#define TVP_R_FGAIN 0x0A +#define TVP_B_FOFFSET_MSB 0x0B +#define TVP_G_FOFFSET_MSB 0x0C +#define TVP_R_FOFFSET_MSB 0x0D +#define TVP_SYNCCTRL1 0x0E +#define TVP_HPLLCTRL2 0x0F + +#define TVP_SOGTHOLD 0x10 +#define TVP_SSTHOLD 0x11 +#define TVP_HPLLPRECOAST 0x12 +#define TVP_HPLLPOSTCOAST 0x13 +#define TVP_SYNCSTAT 0x14 +#define TVP_OUTFORMAT 0x15 +#define TVP_MISCCTRL1 0x16 +#define TVP_MISCCTRL2 0x17 +#define TVP_MISCCTRL3 0x18 +#define TVP_INPMUX1 0x19 +#define TVP_INPMUX2 0x1A +#define TVP_BG_CGAIN 0x1B +#define TVP_R_CGAIN 0x1C +#define TVP_FOFFSET_LSB 0x1D +#define TVP_B_COFFSET 0x1E +#define TVP_G_COFFSET 0x1F + +#define TVP_R_COFFSET 0x20 +#define TVP_HSOUTSTART 0x21 +#define TVP_MISCCTRL4 0x22 +#define TVP_B_ALCOUT_LSB 0x23 +#define TVP_G_ALCOUT_LSB 0x24 +#define TVP_R_ALCOUT_LSB 0x25 +#define TVP_ALCEN 0x26 +#define TVP_ALCOUT_MSB 0x27 +#define TVP_ALCFILT 0x28 +#define TVP_FCLAMPCTRL 0x2A +#define TVP_POWERCTRL 0x2B +#define TVP_ADCSETUP 0x2C +#define TVP_CCLAMPCTRL 0x2D +#define TVP_SOGCLAMP 0x2E +#define TVP_RGBCCLAMPCTRL 0x2F + +#define TVP_SOGCCLAMPCTRL 0x30 +#define TVP_ALCPLACE 0x31 +#define TVP_MVSWIDTH 0x34 +#define TVP_VSOUTALIGN 0x35 +#define TVP_SYNCBYPASS 0x36 +#define TVP_LINECNT1 0x37 +#define TVP_LINECNT2 0x38 +#define TVP_CLKCNT1 0x39 +#define TVP_CLKCNT2 0x3A +#define TVP_HSINWIDTH 0x3B +#define TVP_VSINWIDTH 0x3C +#define TVP_LINELENTOL 0x3D +#define TVP_VIDEOBWLIM 0x3F + +#define TVP_AVIDSTART1 0x40 +#define TVP_AVIDSTART2 0x41 +#define TVP_AVIDSTOP1 0x42 +#define TVP_AVIDSTOP2 0x43 +#define TVP_VB0OFF 0x44 +#define TVP_VB1OFF 0x45 +#define TVP_VB0DUR 0x46 +#define TVP_VB1DUR 0x47 +#define TVP_CSC1LO 0x4A +#define TVP_CSC1HI 0x4B +#define TVP_CSC2LO 0x4C +#define TVP_CSC2HI 0x4D +#define TVP_CSC3LO 0x4E +#define TVP_CSC3HI 0x4F + +#define TVP_CSC4LO 0x50 +#define TVP_CSC4HI 0x51 +#define TVP_CSC5LO 0x52 +#define TVP_CSC5HI 0x53 +#define TVP_CSC6LO 0x54 +#define TVP_CSC6HI 0x55 +#define TVP_CSC7LO 0x56 +#define TVP_CSC7HI 0x57 +#define TVP_CSC8LO 0x58 +#define TVP_CSC8HI 0x59 +#define TVP_CSC9LO 0x5A +#define TVP_CSC9HI 0x5B + +#endif /* TVP7002_REGS_H_ */ diff --git a/software/sys_controller/tvp7002/video_modes.c b/software/sys_controller/tvp7002/video_modes.c new file mode 100644 index 0000000..e2fac1b --- /dev/null +++ b/software/sys_controller/tvp7002/video_modes.c @@ -0,0 +1,85 @@ +// +// Copyright (C) 2015 Markus Hiienkari +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include "system.h" +#include "video_modes.h" + +#define LINECNT_MAX_TOLERANCE 30 + +const mode_data_t video_modes[] = { + { "240p_L3M0", 1280, 240, 6000, 1704, 262, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), MODE_L3_MODE0 }, + { "240p_L3M1", 960, 240, 6000, 1278, 262, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), MODE_L3_MODE1 }, + { "240p_L3M2", 320, 240, 6000, 426, 262, 49, 16, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) }, + { "240p_L3M3", 256, 240, 6000, 341, 262, 39, 16, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) }, + { "240p", 720, 240, 6000, 858, 262, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE) }, + { "288p", 720, 288, 5000, 864, 312, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE) }, + { "384p", 496, 384, 5766, 640, 423, 50, 29, 62, 3, VIDEO_EDTV, (MODE_L2ENABLE) }, //Sega Model 2 + { "640x384", 640, 384, 5500, 800, 492, 48, 63, 96, 2, VIDEO_PC, (MODE_L2ENABLE) }, //X68k @ 24kHz + { "480i", 720, 240, 5994, 858, 525, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_INTERLACED) }, + { "480p", 720, 480, 5994, 858, 525, 60, 30, 62, 6, (VIDEO_EDTV|VIDEO_PC), (MODE_DTV480P) }, + { "640x480", 640, 480, 6000, 800, 525, 48, 33, 96, 2, (VIDEO_PC|VIDEO_EDTV), (MODE_VGA480P) }, + { "640x512", 640, 512, 6000, 800, 568, 48, 28, 96, 2, VIDEO_PC, 0 }, //X68k @ 31kHz + { "576i", 720, 288, 5000, 864, 625, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_INTERLACED) }, + { "576p", 720, 576, 5000, 864, 625, 65, 32, 60, 6, VIDEO_EDTV, 0 }, + { "800x600", 800, 600, 6000, 1056, 628, 88, 23, 128, 4, VIDEO_PC, 0 }, + { "720p", 1280, 720, 5994, 1650, 750, 255, 20, 40, 5, VIDEO_HDTV, 0 }, + { "1280x720", 1280, 720, 6000, 1650, 750, 220, 20, 40, 5, VIDEO_PC, 0 }, + { "1024x768", 1024, 768, 6000, 1344, 806, 160, 29, 136, 6, VIDEO_PC, 0 }, + { "1280x1024", 1280, 1024, 6000, 1688, 1066, 248, 38, 112, 3, VIDEO_PC, 0 }, + { "1080i", 1920, 1080, 5994, 2200, 1125, 148, 16, 44, 5, VIDEO_HDTV, (MODE_L2ENABLE|MODE_INTERLACED) }, //Too high freq for L2 PLL + { "1080p", 1920, 1080, 5994, 2200, 1125, 188, 36, 44, 5, VIDEO_HDTV, 0 }, + { "1920x1080", 1920, 1080, 6000, 2200, 1125, 148, 36, 44, 5, VIDEO_PC, 0 }, +}; + +/* TODO: rewrite, check hz etc. */ +alt_8 get_mode_id(alt_u32 totlines, alt_u8 progressive, alt_u32 hz, video_type typemask, alt_u8 linemult_target, alt_u8 l3_mode, alt_u8 s480p_mode) { + alt_8 i; + alt_u8 num_modes = sizeof(video_modes)/sizeof(mode_data_t); + video_type mode_type; + + // TODO: a better check + for (i=0; i +// +// This file is part of Open Source Scan Converter project. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef VIDEO_MODES_H_ +#define VIDEO_MODES_H_ + +#include +#include "sysconfig.h" + +typedef enum { + FORMAT_RGBS = 0, + FORMAT_RGBHV = 1, + FORMAT_RGsB = 2, + FORMAT_YPbPr = 3 +} video_format; + +typedef enum { + VIDEO_LDTV = (1<<0), + VIDEO_SDTV = (1<<1), + VIDEO_EDTV = (1<<2), + VIDEO_HDTV = (1<<3), + VIDEO_PC = (1<<4) +} video_type; + +#define MODE_L3ENABLE_MASK 0xf + +typedef enum { + MODE_L3_MODE0 = (1<<0), + MODE_L3_MODE1 = (1<<1), + MODE_L3_MODE2 = (1<<2), + MODE_L3_MODE3 = (1<<3), + MODE_L2ENABLE = (1<<4), + MODE_INTERLACED = (1<<5), + MODE_PLLDIVBY2 = (1<<6), + MODE_DTV480P = (1<<7), + MODE_VGA480P = (1<<8) +} mode_flags; + +typedef struct { + char name[10]; + alt_u16 h_active; + alt_u16 v_active; + alt_u16 hz_x100; + alt_u16 h_total; + alt_u16 v_total; + alt_u8 h_backporch; + alt_u8 v_backporch; + alt_u8 h_synclen; + alt_u8 v_synclen; + video_type type; + mode_flags flags; +} mode_data_t; + +alt_8 get_mode_id(alt_u32 totlines, alt_u8 progressive, alt_u32 hz, video_type typemask, alt_u8 linemult_target, alt_u8 l3_mode, alt_u8 s480p_mode); + +#endif /* VIDEO_MODES_H_ */ diff --git a/software/sys_controller_bsp/HAL/inc/alt_types.h b/software/sys_controller_bsp/HAL/inc/alt_types.h new file mode 100644 index 0000000..d02f171 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/alt_types.h @@ -0,0 +1,54 @@ +#ifndef __ALT_TYPES_H__ +#define __ALT_TYPES_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/* + * Don't declare these typedefs if this file is included by assembly source. + */ +#ifndef ALT_ASM_SRC +typedef signed char alt_8; +typedef unsigned char alt_u8; +typedef signed short alt_16; +typedef unsigned short alt_u16; +typedef signed long alt_32; +typedef unsigned long alt_u32; +typedef long long alt_64; +typedef unsigned long long alt_u64; +#endif + +#define ALT_INLINE __inline__ +#define ALT_ALWAYS_INLINE __attribute__ ((always_inline)) +#define ALT_WEAK __attribute__((weak)) + +#endif /* __ALT_TYPES_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/altera_nios2_gen2_irq.h b/software/sys_controller_bsp/HAL/inc/altera_nios2_gen2_irq.h new file mode 100644 index 0000000..42361c7 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/altera_nios2_gen2_irq.h @@ -0,0 +1,80 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * Support for the Nios II internal interrupt controller. + */ + +#ifndef __ALT_NIOS2_GEN2_IRQ_H__ +#define __ALT_NIOS2_GEN2_IRQ_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The macro ALTERA_NIOS2_GEN2_IRQ_INSTANCE is used by the alt_irq_init() + * function in the auto-generated file alt_sys_init.c to create an + * instance of this interrupt controller device driver state if this + * module contains an interrupt controller. + * Only one instance of a Nios II is allowed so this macro is just empty. + */ + +#define ALTERA_NIOS2_GEN2_IRQ_INSTANCE(name, state) + +/* + * altera_nios2_gen2_irq_init() is called by the auto-generated function + * alt_irq_init() once for the Nios II if it contains an interrupt controller. + * The altera_nios2_gen2_irq_init() routine is called using the + * ALTERA_NIOS2_GEN2_IRQ_INIT macro given below. + * + * This function initializes the internal interrupt controller + * so is not called if the Nios II contains an external interrupt + * controller port (because the internal interrupt controller + * is removed if this port is present). + */ + +extern void altera_nios2_gen2_irq_init( void ); + +/* + * The macro ALTERA_NIOS2_GEN2_IRQ_INIT is used by the alt_irq_init() routine + * in the auto-generated file alt_sys_init.c to initialize an instance + * of the interrupt controller device driver state. + */ + +#define ALTERA_NIOS2_GEN2_IRQ_INIT(name, state) altera_nios2_gen2_irq_init() + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_NIOS2_ULTRA_IRQ_H__ */ + diff --git a/software/sys_controller_bsp/HAL/inc/io.h b/software/sys_controller_bsp/HAL/inc/io.h new file mode 100644 index 0000000..912b286 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/io.h @@ -0,0 +1,81 @@ +#ifndef __IO_H__ +#define __IO_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/* IO Header file for Nios II Toolchain */ + +#include "alt_types.h" +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef SYSTEM_BUS_WIDTH +#define SYSTEM_BUS_WIDTH 32 +#endif + +/* Dynamic bus access functions */ + +#define __IO_CALC_ADDRESS_DYNAMIC(BASE, OFFSET) \ + ((void *)(((alt_u8*)BASE) + (OFFSET))) + +#define IORD_32DIRECT(BASE, OFFSET) \ + __builtin_ldwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET))) +#define IORD_16DIRECT(BASE, OFFSET) \ + __builtin_ldhuio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET))) +#define IORD_8DIRECT(BASE, OFFSET) \ + __builtin_ldbuio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET))) + +#define IOWR_32DIRECT(BASE, OFFSET, DATA) \ + __builtin_stwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA)) +#define IOWR_16DIRECT(BASE, OFFSET, DATA) \ + __builtin_sthio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA)) +#define IOWR_8DIRECT(BASE, OFFSET, DATA) \ + __builtin_stbio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA)) + +/* Native bus access functions */ + +#define __IO_CALC_ADDRESS_NATIVE(BASE, REGNUM) \ + ((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8)))) + +#define IORD(BASE, REGNUM) \ + __builtin_ldwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM))) +#define IOWR(BASE, REGNUM, DATA) \ + __builtin_stwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM)), (DATA)) + +#ifdef __cplusplus +} +#endif + +#endif /* __IO_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/nios2.h b/software/sys_controller_bsp/HAL/inc/nios2.h new file mode 100644 index 0000000..663810a --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/nios2.h @@ -0,0 +1,300 @@ +#ifndef __NIOS2_H__ +#define __NIOS2_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * This header provides processor specific macros for accessing the Nios2 + * control registers. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Number of available IRQs in internal interrupt controller. + */ +#define NIOS2_NIRQ 32 + +/* + * Macros for accessing select Nios II general-purpose registers. + */ + +/* ET (Exception Temporary) register */ +#define NIOS2_READ_ET(et) \ + do { __asm ("mov %0, et" : "=r" (et) ); } while (0) + +#define NIOS2_WRITE_ET(et) \ + do { __asm volatile ("mov et, %z0" : : "rM" (et)); } while (0) + +/* SP (Stack Pointer) register */ +#define NIOS2_READ_SP(sp) \ + do { __asm ("mov %0, sp" : "=r" (sp) ); } while (0) + +/* + * Macros for useful processor instructions. + */ +#define NIOS2_BREAK() \ + do { __asm volatile ("break"); } while (0) + +#define NIOS2_REPORT_STACK_OVERFLOW() \ + do { __asm volatile("break 3"); } while (0) + +/* + * Macros for accessing Nios II control registers. + */ +#define NIOS2_READ_STATUS(dest) \ + do { dest = __builtin_rdctl(0); } while (0) + +#define NIOS2_WRITE_STATUS(src) \ + do { __builtin_wrctl(0, src); } while (0) + +#define NIOS2_READ_ESTATUS(dest) \ + do { dest = __builtin_rdctl(1); } while (0) + +#define NIOS2_READ_BSTATUS(dest) \ + do { dest = __builtin_rdctl(2); } while (0) + +#define NIOS2_READ_IENABLE(dest) \ + do { dest = __builtin_rdctl(3); } while (0) + +#define NIOS2_WRITE_IENABLE(src) \ + do { __builtin_wrctl(3, src); } while (0) + +#define NIOS2_READ_IPENDING(dest) \ + do { dest = __builtin_rdctl(4); } while (0) + +#define NIOS2_READ_CPUID(dest) \ + do { dest = __builtin_rdctl(5); } while (0) + +#define NIOS2_READ_EXCEPTION(dest) \ + do { dest = __builtin_rdctl(7); } while (0) + +#define NIOS2_READ_PTEADDR(dest) \ + do { dest = __builtin_rdctl(8); } while (0) + +#define NIOS2_WRITE_PTEADDR(src) \ + do { __builtin_wrctl(8, src); } while (0) + +#define NIOS2_READ_TLBACC(dest) \ + do { dest = __builtin_rdctl(9); } while (0) + +#define NIOS2_WRITE_TLBACC(src) \ + do { __builtin_wrctl(9, src); } while (0) + +#define NIOS2_READ_TLBMISC(dest) \ + do { dest = __builtin_rdctl(10); } while (0) + +#define NIOS2_WRITE_TLBMISC(src) \ + do { __builtin_wrctl(10, src); } while (0) + +#define NIOS2_READ_ECCINJ(dest) \ + do { dest = __builtin_rdctl(11); } while (0) + +#define NIOS2_WRITE_ECCINJ(src) \ + do { __builtin_wrctl(11, src); } while (0) + +#define NIOS2_READ_BADADDR(dest) \ + do { dest = __builtin_rdctl(12); } while (0) + +#define NIOS2_WRITE_CONFIG(src) \ + do { __builtin_wrctl(13, src); } while (0) + +#define NIOS2_READ_CONFIG(dest) \ + do { dest = __builtin_rdctl(13); } while (0) + +#define NIOS2_WRITE_MPUBASE(src) \ + do { __builtin_wrctl(14, src); } while (0) + +#define NIOS2_READ_MPUBASE(dest) \ + do { dest = __builtin_rdctl(14); } while (0) + +#define NIOS2_WRITE_MPUACC(src) \ + do { __builtin_wrctl(15, src); } while (0) + +#define NIOS2_READ_MPUACC(dest) \ + do { dest = __builtin_rdctl(15); } while (0) + +/* + * Nios II control registers that are always present + */ +#define NIOS2_STATUS status +#define NIOS2_ESTATUS estatus +#define NIOS2_BSTATUS bstatus +#define NIOS2_IENABLE ienable +#define NIOS2_IPENDING ipending +#define NIOS2_CPUID cpuid + +/* + * Bit masks & offsets for Nios II control registers. + * The presence and size of a field is sometimes dependent on the Nios II + * configuration. Bit masks for every possible field and the maximum size of + * that field are defined. + * + * All bit-masks are expressed relative to the position + * of the data with a register. To read data that is LSB- + * aligned, the register read data should be masked, then + * right-shifted by the designated "OFST" macro value. The + * opposite should be used for register writes when starting + * with LSB-aligned data. + */ + +/* STATUS, ESTATUS, BSTATUS, and SSTATUS registers */ +#define NIOS2_STATUS_PIE_MSK (0x00000001) +#define NIOS2_STATUS_PIE_OFST (0) +#define NIOS2_STATUS_U_MSK (0x00000002) +#define NIOS2_STATUS_U_OFST (1) +#define NIOS2_STATUS_EH_MSK (0x00000004) +#define NIOS2_STATUS_EH_OFST (2) +#define NIOS2_STATUS_IH_MSK (0x00000008) +#define NIOS2_STATUS_IH_OFST (3) +#define NIOS2_STATUS_IL_MSK (0x000003f0) +#define NIOS2_STATUS_IL_OFST (4) +#define NIOS2_STATUS_CRS_MSK (0x0000fc00) +#define NIOS2_STATUS_CRS_OFST (10) +#define NIOS2_STATUS_PRS_MSK (0x003f0000) +#define NIOS2_STATUS_PRS_OFST (16) +#define NIOS2_STATUS_NMI_MSK (0x00400000) +#define NIOS2_STATUS_NMI_OFST (22) +#define NIOS2_STATUS_RSIE_MSK (0x00800000) +#define NIOS2_STATUS_RSIE_OFST (23) +#define NIOS2_STATUS_SRS_MSK (0x80000000) +#define NIOS2_STATUS_SRS_OFST (31) + +/* EXCEPTION register */ +#define NIOS2_EXCEPTION_REG_CAUSE_MASK (0x0000007c) +#define NIOS2_EXCEPTION_REG_CAUSE_OFST (2) +#define NIOS2_EXCEPTION_REG_ECCFTL_MASK (0x80000000) +#define NIOS2_EXCEPTION_REG_ECCFTL_OFST (31) + +/* PTEADDR (Page Table Entry Address) register */ +#define NIOS2_PTEADDR_REG_VPN_OFST 2 +#define NIOS2_PTEADDR_REG_VPN_MASK 0x3ffffc +#define NIOS2_PTEADDR_REG_PTBASE_OFST 22 +#define NIOS2_PTEADDR_REG_PTBASE_MASK 0xffc00000 + +/* TLBACC (TLB Access) register */ +#define NIOS2_TLBACC_REG_PFN_OFST 0 +#define NIOS2_TLBACC_REG_PFN_MASK 0xfffff +#define NIOS2_TLBACC_REG_G_OFST 20 +#define NIOS2_TLBACC_REG_G_MASK 0x100000 +#define NIOS2_TLBACC_REG_X_OFST 21 +#define NIOS2_TLBACC_REG_X_MASK 0x200000 +#define NIOS2_TLBACC_REG_W_OFST 22 +#define NIOS2_TLBACC_REG_W_MASK 0x400000 +#define NIOS2_TLBACC_REG_R_OFST 23 +#define NIOS2_TLBACC_REG_R_MASK 0x800000 +#define NIOS2_TLBACC_REG_C_OFST 24 +#define NIOS2_TLBACC_REG_C_MASK 0x1000000 +#define NIOS2_TLBACC_REG_IG_OFST 25 +#define NIOS2_TLBACC_REG_IG_MASK 0xfe000000 + +/* TLBMISC (TLB Miscellaneous) register */ +#define NIOS2_TLBMISC_REG_D_OFST 0 +#define NIOS2_TLBMISC_REG_D_MASK 0x1 +#define NIOS2_TLBMISC_REG_PERM_OFST 1 +#define NIOS2_TLBMISC_REG_PERM_MASK 0x2 +#define NIOS2_TLBMISC_REG_BAD_OFST 2 +#define NIOS2_TLBMISC_REG_BAD_MASK 0x4 +#define NIOS2_TLBMISC_REG_DBL_OFST 3 +#define NIOS2_TLBMISC_REG_DBL_MASK 0x8 +#define NIOS2_TLBMISC_REG_PID_OFST 4 +#define NIOS2_TLBMISC_REG_PID_MASK 0x3fff0 +#define NIOS2_TLBMISC_REG_WE_OFST 18 +#define NIOS2_TLBMISC_REG_WE_MASK 0x40000 +#define NIOS2_TLBMISC_REG_RD_OFST 19 +#define NIOS2_TLBMISC_REG_RD_MASK 0x80000 +#define NIOS2_TLBMISC_REG_WAY_OFST 20 +#define NIOS2_TLBMISC_REG_WAY_MASK 0xf00000 +#define NIOS2_TLBMISC_REG_EE_OFST 24 +#define NIOS2_TLBMISC_REG_EE_MASK 0x1000000 + +/* ECCINJ (ECC Inject) register */ +#define NIOS2_ECCINJ_REG_RF_OFST 0 +#define NIOS2_ECCINJ_REG_RF_MASK 0x3 +#define NIOS2_ECCINJ_REG_ICTAG_OFST 2 +#define NIOS2_ECCINJ_REG_ICTAG_MASK 0xc +#define NIOS2_ECCINJ_REG_ICDAT_OFST 4 +#define NIOS2_ECCINJ_REG_ICDAT_MASK 0x30 +#define NIOS2_ECCINJ_REG_DCTAG_OFST 6 +#define NIOS2_ECCINJ_REG_DCTAG_MASK 0xc0 +#define NIOS2_ECCINJ_REG_DCDAT_OFST 8 +#define NIOS2_ECCINJ_REG_DCDAT_MASK 0x300 +#define NIOS2_ECCINJ_REG_TLB_OFST 10 +#define NIOS2_ECCINJ_REG_TLB_MASK 0xc00 +#define NIOS2_ECCINJ_REG_DTCM0_OFST 12 +#define NIOS2_ECCINJ_REG_DTCM0_MASK 0x3000 +#define NIOS2_ECCINJ_REG_DTCM1_OFST 14 +#define NIOS2_ECCINJ_REG_DTCM1_MASK 0xc000 +#define NIOS2_ECCINJ_REG_DTCM2_OFST 16 +#define NIOS2_ECCINJ_REG_DTCM2_MASK 0x30000 +#define NIOS2_ECCINJ_REG_DTCM3_OFST 18 +#define NIOS2_ECCINJ_REG_DTCM3_MASK 0xc0000 + +/* CONFIG register */ +#define NIOS2_CONFIG_REG_PE_MASK (0x00000001) +#define NIOS2_CONFIG_REG_PE_OFST (0) +#define NIOS2_CONFIG_REG_ANI_MASK (0x00000002) +#define NIOS2_CONFIG_REG_ANI_OFST (1) +#define NIOS2_CONFIG_REG_ECCEN_MASK (0x00000004) +#define NIOS2_CONFIG_REG_ECCEN_OFST (2) +#define NIOS2_CONFIG_REG_ECCEXC_MASK (0x00000008) +#define NIOS2_CONFIG_REG_ECCEXC_OFST (3) + +/* MPUBASE (MPU Base Address) Register */ +#define NIOS2_MPUBASE_D_MASK (0x00000001) +#define NIOS2_MPUBASE_D_OFST (0) +#define NIOS2_MPUBASE_INDEX_MASK (0x0000003e) +#define NIOS2_MPUBASE_INDEX_OFST (1) +#define NIOS2_MPUBASE_BASE_ADDR_MASK (0xffffffc0) +#define NIOS2_MPUBASE_BASE_ADDR_OFST (6) + +/* MPUACC (MPU Access) Register */ +#define NIOS2_MPUACC_LIMIT_MASK (0xffffffc0) +#define NIOS2_MPUACC_LIMIT_OFST (6) +#define NIOS2_MPUACC_MASK_MASK (0xffffffc0) +#define NIOS2_MPUACC_MASK_OFST (6) +#define NIOS2_MPUACC_C_MASK (0x00000020) +#define NIOS2_MPUACC_C_OFST (5) +#define NIOS2_MPUACC_PERM_MASK (0x0000001c) +#define NIOS2_MPUACC_PERM_OFST (2) +#define NIOS2_MPUACC_RD_MASK (0x00000002) +#define NIOS2_MPUACC_RD_OFST (1) +#define NIOS2_MPUACC_WR_MASK (0x00000001) +#define NIOS2_MPUACC_WR_OFST (0) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __NIOS2_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/os/alt_flag.h b/software/sys_controller_bsp/HAL/inc/os/alt_flag.h new file mode 100644 index 0000000..b9b4605 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/os/alt_flag.h @@ -0,0 +1,98 @@ +#ifndef __ALT_FLAG_H__ +#define __ALT_FLAG_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * This header provides macro definitions that can be used to create and use + * uc/OS-II style event flags. These macros can be used in both a uC/OS-II based + * environment, and a single threaded HAL based environment. + * + * The motivation for these macros is to allow code to be developed which is + * thread safe under uC/OS-II, but incurs no additional overhead when used in a + * single threaded HAL environment. + * + * In the case of a single threaded HAL environment, they compile to + * "do nothing" directives, which ensures they do not contribute to the final + * executable. + * + * The following macros are available: + * + * ALT_FLAG_GRP - Create a flag group instance. + * ALT_EXTERN_FLAG_GRP - Create a reference to an external flag group instance. + * ALT_STATIC_FLAG_GRP - Create a static flag group instance. + * ALT_FLAG_CREATE - Initialise a flag group. + * ALT_FLAG_PEND - Pend on a flag group. + * ALT_FLAG_POST - Set a flag condition. + + * + * Input arguments and return codes are all consistant with the equivalent + * uC/OS-II function. + * + * It's important to be careful in the use of the macros: ALT_FLAG_GRP, + * ALT_EXTERN_FLAG_GRP, and ALT_STATIC_FLAG_GRP. In these three cases the + * semi-colon is included in the macro definition; so, for example, you should + * use: + * + * ALT_FLAG_GRP(mygroup) + * + * not: + * + * ALT_FLAG_GRP(mygroup); + * + * The inclusion of the semi-colon has been necessary to ensure the macros can + * compile with no warnings when used in a single threaded HAL environment. + * + */ + +#include "priv/alt_no_error.h" + +#define ALT_FLAG_GRP(group) +#define ALT_EXTERN_FLAG_GRP(group) +#define ALT_STATIC_FLAG_GRP(group) + +#define ALT_FLAG_CREATE(group, flags) alt_no_error () +#define ALT_FLAG_PEND(group, flags, wait_type, timeout) alt_no_error () +#define ALT_FLAG_POST(group, flags, opt) alt_no_error () + +#ifndef ALT_SINGLE_THREADED +#define ALT_SINGLE_THREADED +#endif + +#endif /* __ALT_FLAG_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/os/alt_hooks.h b/software/sys_controller_bsp/HAL/inc/os/alt_hooks.h new file mode 100644 index 0000000..9054e3f --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/os/alt_hooks.h @@ -0,0 +1,61 @@ +#ifndef __ALT_HOOKS_H__ +#define __ALT_HOOKS_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * This header provides "do-nothing" macro definitions for operating system + * hooks within the HAL. The O/S component can override these to provide it's + * own implementation. + */ + +#define ALT_OS_TIME_TICK() while(0) +#define ALT_OS_INIT() while(0) +#define ALT_OS_STOP() while(0) + +/* Call from assembly code */ +#define ALT_OS_INT_ENTER_ASM +#define ALT_OS_INT_EXIT_ASM + +/* Call from C code */ +#define ALT_OS_INT_ENTER() while(0) +#define ALT_OS_INT_EXIT() while(0) + + +#endif /* __ALT_HOOKS_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/os/alt_sem.h b/software/sys_controller_bsp/HAL/inc/os/alt_sem.h new file mode 100644 index 0000000..753943e --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/os/alt_sem.h @@ -0,0 +1,96 @@ +#ifndef __ALT_SEM_H__ +#define __ALT_SEM_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * This header provides macro definitions that can be used to create and use + * semaphores. These macros can be used in both a uC/OS-II based environment, + * and a single threaded HAL based environment. + * + * The motivation for these macros is to allow code to be developed which is + * thread safe under uC/OS-II, but incurs no additional overhead when used in a + * single threaded HAL environment. + * + * In the case of a single threaded HAL environment, they compile to + * "do nothing" directives, which ensures they do not contribute to the final + * executable. + * + * The following macros are available: + * + * ALT_SEM - Create a semaphore instance. + * ALT_EXTERN_SEM - Create a reference to an external semaphore instance. + * ALT_STATIC_SEM - Create a static semaphore instance. + * ALT_SEM_CREATE - Initialise a semaphore. + * ALT_SEM_PEND - Pend on a semaphore. + * ALT_SEM_POST - Increment a semaphore. + * + * Input arguments and return codes are all consistant with the equivalent + * uC/OS-II function. + * + * It's important to be careful in the use of the macros: ALT_SEM, + * ALT_EXTERN_SEM, and ALT_STATIC_SEM. In these three cases the semi-colon is + * included in the macro definition; so, for example, you should use: + * + * ALT_SEM(mysem) + * + * not: + * + * ALT_SEM(mysem); + * + * The inclusion of the semi-colon has been necessary to ensure the macros can + * compile with no warnings when used in a single threaded HAL environment. + * + */ + +#include "priv/alt_no_error.h" + +#define ALT_SEM(sem) +#define ALT_EXTERN_SEM(sem) +#define ALT_STATIC_SEM(sem) + +#define ALT_SEM_CREATE(sem, value) alt_no_error () +#define ALT_SEM_PEND(sem, timeout) alt_no_error () +#define ALT_SEM_POST(sem) alt_no_error () + +#ifndef ALT_SINGLE_THREADED +#define ALT_SINGLE_THREADED +#endif + +#endif /* __ALT_SEM_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/os/alt_syscall.h b/software/sys_controller_bsp/HAL/inc/os/alt_syscall.h new file mode 100644 index 0000000..507c6aa --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/os/alt_syscall.h @@ -0,0 +1,75 @@ +#ifndef __ALT_SYSCALL_H__ +#define __ALT_SYSCALL_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * The macros defined in this file are used to provide the function names used + * for the HAL 'UNIX style' interface, e.g. read(), write() etc. + * + * Operating systems which are ported to the HAL can provide their own + * version of this file, which will be used in preference. This allows + * the operating system to provide it's own implementation of the top level + * system calls, while retaining the HAL functions under a different name, + * for example, alt_read(), alt_write() etc. + */ + +#define ALT_CLOSE close +#define ALT_ENVIRON environ +#define ALT_EXECVE execve +#define ALT_EXIT _exit +#define ALT_FCNTL fcntl +#define ALT_FORK fork +#define ALT_FSTAT fstat +#define ALT_GETPID getpid +#define ALT_GETTIMEOFDAY gettimeofday +#define ALT_IOCTL ioctl +#define ALT_ISATTY isatty +#define ALT_KILL kill +#define ALT_LINK link +#define ALT_LSEEK lseek +#define ALT_OPEN open +#define ALT_READ read +#define ALT_RENAME _rename +#define ALT_SBRK sbrk +#define ALT_SETTIMEOFDAY settimeofday +#define ALT_STAT stat +#define ALT_UNLINK unlink +#define ALT_USLEEP usleep +#define ALT_WAIT wait +#define ALT_WRITE write +#define ALT_TIMES times + +/* + * + */ + +#endif /* __ALT_SYSCALL_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_alarm.h b/software/sys_controller_bsp/HAL/inc/priv/alt_alarm.h new file mode 100644 index 0000000..45d6a0e --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_alarm.h @@ -0,0 +1,101 @@ +#ifndef __ALT_PRIV_ALARM_H__ +#define __ALT_PRIV_ALARM_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "alt_types.h" + +/* + * This header provides the internal defenitions required by the public + * interface alt_alarm.h. These variables and structures are not guaranteed to + * exist in future implementations of the HAL. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * "alt_alarm_s" is a structure type used to maintain lists of alarm callback + * functions. + */ + +struct alt_alarm_s +{ + alt_llist llist; /* linked list */ + alt_u32 time; /* time in system ticks of the callback */ + alt_u32 (*callback) (void* context); /* callback function. The return + * value is the period for the next callback; where + * zero indicates that the alarm should be removed + * from the list. + */ + alt_u8 rollover; /* set when desired alarm time + current time causes + overflow, to prevent premature alarm */ + void* context; /* Argument for the callback */ +}; + +/* + * "_alt_tick_rate" is a global variable used to store the system clock rate + * in ticks per second. This is initialised to zero, which coresponds to there + * being no system clock available. + * + * It is then set to it's final value by the system clock driver through a call + * to alt_sysclk_init(). + */ + +extern alt_u32 _alt_tick_rate; + +/* + * "_alt_nticks" is a global variable which records the elapsed number of + * system clock ticks since the last call to settimeofday() or since reset if + * settimeofday() has not been called. + */ + +extern volatile alt_u32 _alt_nticks; + +/* The list of registered alarms. */ + +extern alt_llist alt_alarm_list; + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_PRIV_ALARM_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_busy_sleep.h b/software/sys_controller_bsp/HAL/inc/priv/alt_busy_sleep.h new file mode 100644 index 0000000..b1af849 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_busy_sleep.h @@ -0,0 +1,35 @@ +#ifndef __ALT_BUSY_SLEEP_H +#define __ALT_BUSY_SLEEP_H + +/* + * Copyright (c) 2003 Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* + * The function alt_busy_sleep provides a busy loop implementation of usleep. + * This is used to provide usleep for the standalone HAL, or when the timer is + * unavailable in uC/OS-II. + */ + +extern unsigned int alt_busy_sleep (unsigned int us); + +#endif /* __ALT_BUSY_SLEEP_H */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_dev_llist.h b/software/sys_controller_bsp/HAL/inc/priv/alt_dev_llist.h new file mode 100644 index 0000000..451b063 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_dev_llist.h @@ -0,0 +1,77 @@ +#ifndef __ALT_DEV_LLIST_H__ +#define __ALT_DEV_LLIST_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "sys/alt_llist.h" +#include "alt_types.h" + +/* + * This header provides the internal defenitions required to control file + * access. These variables and functions are not guaranteed to exist in + * future implementations of the HAL. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The alt_dev_llist is an internal structure used to form a common base + * class for all device types. The use of this structure allows common code + * to be used to manipulate the various device lists. + */ + +typedef struct { + alt_llist llist; + const char* name; +} alt_dev_llist; + +/* + * + */ + +extern int alt_dev_llist_insert (alt_dev_llist* dev, alt_llist* list); + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_DEV_LLIST_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_exception_handler_registry.h b/software/sys_controller_bsp/HAL/inc/priv/alt_exception_handler_registry.h new file mode 100644 index 0000000..c6905fa --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_exception_handler_registry.h @@ -0,0 +1,39 @@ +#ifndef __ALT_EXCEPTION_HANDLER_REGISTRY_H__ +#define __ALT_EXCEPTION_HANDLER_REGISTRY_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ +#include "sys/alt_exceptions.h" + +/* Function pointer to exception callback routine */ +extern alt_exception_result (*alt_instruction_exception_handler) + (alt_exception_cause, alt_u32, alt_u32); + +#endif /* __ALT_EXCEPTION_HANDLER_REGISTRY_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_file.h b/software/sys_controller_bsp/HAL/inc/priv/alt_file.h new file mode 100644 index 0000000..2c3e843 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_file.h @@ -0,0 +1,179 @@ +#ifndef __ALT_FILE_H__ +#define __ALT_FILE_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "sys/alt_dev.h" +#include "sys/alt_llist.h" +#include "os/alt_sem.h" + +#include "alt_types.h" + +/* + * This header provides the internal defenitions required to control file + * access. These variables and functions are not guaranteed to exist in + * future implementations of the HAL. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The function alt_find_dev() is used to search the device list "list" to + * locate a device named "name". If a match is found, then a pointer to the + * device is returned, otherwise NULL is returned. + */ + +extern alt_dev* alt_find_dev (const char* name, alt_llist* list); + +/* + * alt_find_file() is used to search the list of registered file systems to + * find the filesystem that the file named "name" belongs to. If a match is + * found, then a pointer to the filesystems alt_dev structure is returned, + * otherwise NULL is returned. + * + * Note that a match does not indicate that the file exists, only that a + * filesystem exists that is registered for a partition that could contain + * the file. The filesystems open() function would need to be called in order + * to determine if the file exists. + */ + +extern alt_dev* alt_find_file (const char* name); + +/* + * alt_get_fd() is used to allocate a file descriptor for the device or + * filesystem "dev". A negative return value indicates an error, otherwise the + * return value is the index of the file descriptor within the file descriptor + * pool. + */ + +extern int alt_get_fd (alt_dev* dev); + +/* + * alt_release_fd() is called to free the file descriptor with index "fd". + */ + +extern void alt_release_fd (int fd); + +/* + * alt_fd_lock() is called by ioctl() to mark the file descriptor "fd" as + * being open for exclusive access. Subsequent calls to open() for the device + * associated with "fd" will fail. A device is unlocked by either calling + * close() for "fd", or by an alternate call to ioctl() (see ioctl.c for + * details). + */ + +extern int alt_fd_lock (alt_fd* fd); + +/* + * alt_fd_unlock() is called by ioctl() to unlock a descriptor previously + * locked by a call to alt_fd_lock(). + */ + +extern int alt_fd_unlock (alt_fd* fd); + +/* + * "alt_fd_list" is the pool of file descriptors. + */ + +extern alt_fd alt_fd_list[]; + +/* + * flags used by alt_fd. + * + * ALT_FD_EXCL is used to mark a file descriptor as locked for exclusive + * access, i.e. further calls to open() for the associated device should + * fail. + * + * ALT_FD_DEV marks a dile descriptor as belonging to a device as oposed to a + * filesystem. + */ + +#define ALT_FD_EXCL 0x80000000 +#define ALT_FD_DEV 0x40000000 + +#define ALT_FD_FLAGS_MASK (ALT_FD_EXCL | ALT_FD_DEV) + +/* + * "alt_dev_list" is the head of the linked list of registered devices. + */ + +extern alt_llist alt_dev_list; + +/* + * "alt_fs_list" is the head of the linked list of registered filesystems. + */ + +extern alt_llist alt_fs_list; + +/* + * "alt_fd_list_lock" is a semaphore used to ensure that access to the pool + * of file descriptors is thread safe. + */ + +ALT_EXTERN_SEM(alt_fd_list_lock) + +/* + * "alt_max_fd" is a 'high water mark'. It indicates the highest file + * descriptor allocated. Use of this can save searching the entire pool + * for active file descriptors, which helps avoid contention on access + * to the file descriptor pool. + */ + +extern alt_32 alt_max_fd; + +/* + * alt_io_redirect() is called at startup to redirect stdout, stdin, and + * stderr to the devices named in the input arguments. By default these streams + * are directed at /dev/null, and are then redirected using this function once + * all of the devices have been registered within the system. + */ + +extern void alt_io_redirect(const char* stdout_dev, + const char* stdin_dev, + const char* stderr_dev); + + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_FILE_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_iic_isr_register.h b/software/sys_controller_bsp/HAL/inc/priv/alt_iic_isr_register.h new file mode 100644 index 0000000..a0cb01c --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_iic_isr_register.h @@ -0,0 +1,39 @@ +#ifndef __ALT_IIC_ISR_REGISTER_H_ +#define __ALT_IIC_ISR_REGISTER_H_ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ +#include "alt_types.h" +#include "sys/alt_irq.h" + +extern int alt_iic_isr_register(alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, + void *isr_context, void *flags); + +#endif /* __ALT_IIC_ISR_REGISTER_H_ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_irq_table.h b/software/sys_controller_bsp/HAL/inc/priv/alt_irq_table.h new file mode 100644 index 0000000..694ef06 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_irq_table.h @@ -0,0 +1,59 @@ +#ifndef __ALT_IRQ_TABLE_H__ +#define __ALT_IRQ_TABLE_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * Definition of a table describing each interrupt handler. The index into + * the array is the interrupt id associated with the handler. + * + * When an interrupt occurs, the associated handler is called with + * the argument stored in the context member. + * + * The table is physically created in alt_irq_handler.c + */ +extern struct ALT_IRQ_HANDLER +{ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + void (*handler)(void*); +#else + void (*handler)(void*, alt_u32); +#endif + void *context; +} alt_irq[ALT_NIRQ]; + +#endif diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_legacy_irq.h b/software/sys_controller_bsp/HAL/inc/priv/alt_legacy_irq.h new file mode 100644 index 0000000..c7aec02 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_legacy_irq.h @@ -0,0 +1,158 @@ +#ifndef __ALT_LEGACY_IRQ_H__ +#define __ALT_LEGACY_IRQ_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * This file provides prototypes and inline implementations of certain routines + * used by the legacy interrupt API. Do not include this in your driver or + * application source files, use "sys/alt_irq.h" instead to access the proper + * public API. + */ + +#include +#include "system.h" + +#ifndef NIOS2_EIC_PRESENT + +#include "nios2.h" +#include "alt_types.h" + +#include "sys/alt_irq.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * alt_irq_register() can be used to register an interrupt handler. If the + * function is succesful, then the requested interrupt will be enabled upon + * return. + */ +extern int alt_irq_register (alt_u32 id, + void* context, + alt_isr_func handler); + +/* + * alt_irq_disable() disables the individual interrupt indicated by "id". + */ +static ALT_INLINE int ALT_ALWAYS_INLINE alt_irq_disable (alt_u32 id) +{ + alt_irq_context status; + extern volatile alt_u32 alt_irq_active; + + status = alt_irq_disable_all (); + + alt_irq_active &= ~(1 << id); + NIOS2_WRITE_IENABLE (alt_irq_active); + + alt_irq_enable_all(status); + + return 0; +} + +/* + * alt_irq_enable() enables the individual interrupt indicated by "id". + */ +static ALT_INLINE int ALT_ALWAYS_INLINE alt_irq_enable (alt_u32 id) +{ + alt_irq_context status; + extern volatile alt_u32 alt_irq_active; + + status = alt_irq_disable_all (); + + alt_irq_active |= (1 << id); + NIOS2_WRITE_IENABLE (alt_irq_active); + + alt_irq_enable_all(status); + + return 0; +} + +#ifndef ALT_EXCEPTION_STACK +/* + * alt_irq_initerruptable() should only be called from within an ISR. It is used + * to allow higer priority interrupts to interrupt the current ISR. The input + * argument, "priority", is the priority, i.e. interrupt number of the current + * interrupt. + * + * If this function is called, then the ISR is required to make a call to + * alt_irq_non_interruptible() before returning. The input argument to + * alt_irq_non_interruptible() is the return value from alt_irq_interruptible(). + * + * Care should be taken when using this pair of functions, since they increasing + * the system overhead associated with interrupt handling. + * + * If you are using an exception stack then nested interrupts won't work, so + * these functions are not available in that case. + */ +static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_irq_interruptible (alt_u32 priority) +{ + extern volatile alt_u32 alt_priority_mask; + extern volatile alt_u32 alt_irq_active; + + alt_u32 old_priority; + + old_priority = alt_priority_mask; + alt_priority_mask = (1 << priority) - 1; + + NIOS2_WRITE_IENABLE (alt_irq_active & alt_priority_mask); + + NIOS2_WRITE_STATUS (1); + + return old_priority; +} + +/* + * See Comments above for alt_irq_interruptible() for an explanation of the use of this + * function. + */ +static ALT_INLINE void ALT_ALWAYS_INLINE alt_irq_non_interruptible (alt_u32 mask) +{ + extern volatile alt_u32 alt_priority_mask; + extern volatile alt_u32 alt_irq_active; + + NIOS2_WRITE_STATUS (0); + + alt_priority_mask = mask; + + NIOS2_WRITE_IENABLE (mask & alt_irq_active); +} +#endif /* ALT_EXCEPTION_STACK */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* NIOS2_EIC_PRESENT */ + +#endif /* __ALT_LEGACY_IRQ_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/alt_no_error.h b/software/sys_controller_bsp/HAL/inc/priv/alt_no_error.h new file mode 100644 index 0000000..6143fc9 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/alt_no_error.h @@ -0,0 +1,77 @@ +#ifndef __ALT_NO_ERROR_H__ +#define __ALT_NO_ERROR_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "alt_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * alt_no_error() is a dummy function used by alt_sem.h and alt_flag.h. It + * substitutes for functions that have a return code by creating a function + * that always returns zero. + * + * This may seem a little obscure, but what happens is that the compiler can + * then optomise away the call to this function, and any code written which + * handles the error path (i.e. non zero return values). + * + * This allows code to be written which correctly use the uC/OS-II semaphore + * and flag utilities, without the use of those utilities impacting on + * excutables built for a single threaded HAL environment. + * + * This function is considered to be part of the internal implementation of + * the HAL, and should not be called directly by application code or device + * drivers. It is not guaranteed to be preserved in future versions of the + * HAL. + */ + +static ALT_INLINE int ALT_ALWAYS_INLINE alt_no_error (void) +{ + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_NO_ERROR_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/priv/nios2_gmon_data.h b/software/sys_controller_bsp/HAL/inc/priv/nios2_gmon_data.h new file mode 100644 index 0000000..3f43f12 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/priv/nios2_gmon_data.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ +#ifndef NIOS2_GMON_DATA_H +#define NIOS2_GMON_DATA_H + +#define GMON_DATA_SIG 0 +#define GMON_DATA_WORDS 1 +#define GMON_DATA_PROFILE_DATA 2 +#define GMON_DATA_PROFILE_LOWPC 3 +#define GMON_DATA_PROFILE_HIGHPC 4 +#define GMON_DATA_PROFILE_BUCKET 5 +#define GMON_DATA_PROFILE_RATE 6 +#define GMON_DATA_MCOUNT_START 7 +#define GMON_DATA_MCOUNT_LIMIT 8 + +#define GMON_DATA_SIZE 9 + +extern unsigned int alt_gmon_data[GMON_DATA_SIZE]; + +#endif diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_alarm.h b/software/sys_controller_bsp/HAL/inc/sys/alt_alarm.h new file mode 100644 index 0000000..68a2f5d --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_alarm.h @@ -0,0 +1,126 @@ +#ifndef __ALT_ALARM_H__ +#define __ALT_ALARM_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "alt_llist.h" +#include "alt_types.h" + +#include "priv/alt_alarm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * "alt_alarm" is a structure type used by applications to register an alarm + * callback function. An instance of this type must be passed as an input + * argument to alt_alarm_start(). The user is not responsible for initialising + * the contents of the instance. This is done by alt_alarm_start(). + */ + +typedef struct alt_alarm_s alt_alarm; + +/* + * alt_alarm_start() can be called by an application/driver in order to register + * a function for periodic callback at the system clock frequency. Be aware that + * this callback is likely to occur in interrupt context. + */ + +extern int alt_alarm_start (alt_alarm* the_alarm, + alt_u32 nticks, + alt_u32 (*callback) (void* context), + void* context); + +/* + * alt_alarm_stop() is used to unregister a callback. Alternatively the callback + * can return zero to unregister. + */ + +extern void alt_alarm_stop (alt_alarm* the_alarm); + +/* + * Obtain the system clock rate in ticks/s. + */ + +static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_ticks_per_second (void) +{ + return _alt_tick_rate; +} + +/* + * alt_sysclk_init() is intended to be only used by the system clock driver + * in order to initialise the value of the clock frequency. + */ + +static ALT_INLINE int ALT_ALWAYS_INLINE alt_sysclk_init (alt_u32 nticks) +{ + if (! _alt_tick_rate) + { + _alt_tick_rate = nticks; + return 0; + } + else + { + return -1; + } +} + +/* + * alt_nticks() returns the elapsed number of system clock ticks since reset. + */ + +static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_nticks (void) +{ + return _alt_nticks; +} + +/* + * alt_tick() should only be called by the system clock driver. This is used + * to notify the system that the system timer period has expired. + */ + +extern void alt_tick (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_ALARM_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_cache.h b/software/sys_controller_bsp/HAL/inc/sys/alt_cache.h new file mode 100644 index 0000000..c4d8db9 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_cache.h @@ -0,0 +1,117 @@ +#ifndef __ALT_CACHE_H__ +#define __ALT_CACHE_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003, 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include + +#include "alt_types.h" + +/* + * alt_cache.h defines the processor specific functions for manipulating the + * cache. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * alt_icache_flush() is called to flush the instruction cache for a memory + * region of length "len" bytes, starting at address "start". + */ + +extern void alt_icache_flush (void* start, alt_u32 len); + +/* + * alt_dcache_flush() is called to flush the data cache for a memory + * region of length "len" bytes, starting at address "start". + * Any dirty lines in the data cache are written back to memory. + */ + +extern void alt_dcache_flush (void* start, alt_u32 len); + +/* + * alt_dcache_flush() is called to flush the data cache for a memory + * region of length "len" bytes, starting at address "start". + * Any dirty lines in the data cache are NOT written back to memory. + */ + +extern void alt_dcache_flush_no_writeback (void* start, alt_u32 len); + +/* + * Flush the entire instruction cache. + */ + +extern void alt_icache_flush_all (void); + +/* + * Flush the entire data cache. + */ + +extern void alt_dcache_flush_all (void); + +/* + * Allocate a block of uncached memory. + */ + +extern volatile void* alt_uncached_malloc (size_t size); + +/* + * Free a block of uncached memory. + */ + +extern void alt_uncached_free (volatile void* ptr); + +/* + * Convert a pointer to a block of cached memory, into a block of + * uncached memory. + */ + +extern volatile void* alt_remap_uncached (void* ptr, alt_u32 len); + +/* + * Convert a pointer to a block of uncached memory, into a block of + * cached memory. + */ + +extern void* alt_remap_cached (volatile void* ptr, alt_u32 len); + +/* + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_CACHE_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_debug.h b/software/sys_controller_bsp/HAL/inc/sys/alt_debug.h new file mode 100644 index 0000000..d9f9599 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_debug.h @@ -0,0 +1,45 @@ +#ifndef __ALT_DEBUG_H__ +#define __ALT_DEBUG_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * The ALT_DEVUG_ASSERT macro can be used to generate a debugger break + * from within software. The break is generated if "condition" evaluates to + * false. + */ + +#define ALT_DEBUG_ASSERT(condition) if (!condition) \ +{ \ + __asm__ volatile ("break"); \ +} + +#endif /* __ALT_DEBUG_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_dev.h b/software/sys_controller_bsp/HAL/inc/sys/alt_dev.h new file mode 100644 index 0000000..66c5e41 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_dev.h @@ -0,0 +1,115 @@ +#ifndef __ALT_DEV_H__ +#define __ALT_DEV_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "system.h" +#include "sys/alt_llist.h" +#include "priv/alt_dev_llist.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The value ALT_IRQ_NOT_CONNECTED is used to represent an unconnected + * interrupt line. It cannot evaluate to a valid interrupt number. + */ + +#define ALT_IRQ_NOT_CONNECTED (-1) + +typedef struct alt_dev_s alt_dev; + +struct stat; + +/* + * The file descriptor structure definition. + */ + +typedef struct alt_fd_s +{ + alt_dev* dev; + alt_u8* priv; + int fd_flags; +} alt_fd; + +/* + * The device structure definition. + */ + +struct alt_dev_s { + alt_llist llist; /* for internal use */ + const char* name; + int (*open) (alt_fd* fd, const char* name, int flags, int mode); + int (*close) (alt_fd* fd); + int (*read) (alt_fd* fd, char* ptr, int len); + int (*write) (alt_fd* fd, const char* ptr, int len); + int (*lseek) (alt_fd* fd, int ptr, int dir); + int (*fstat) (alt_fd* fd, struct stat* buf); + int (*ioctl) (alt_fd* fd, int req, void* arg); +}; + +/* + * Functions used to register device for access through the C standard + * library. + * + * The only difference between alt_dev_reg() and alt_fs_reg() is the + * interpretation that open() places on the device name. In the case of + * alt_dev_reg the device is assumed to be a particular character device, + * and so there must be an exact match in the name for open to succeed. + * In the case of alt_fs_reg() the name of the device is treated as the + * mount point for a directory, and so any call to open() where the name + * is the root of the device filename will succeed. + */ + +extern int alt_fs_reg (alt_dev* dev); + +static ALT_INLINE int alt_dev_reg (alt_dev* dev) +{ + extern alt_llist alt_dev_list; + + return alt_dev_llist_insert ((alt_dev_llist*) dev, &alt_dev_list); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_DEV_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_dma.h b/software/sys_controller_bsp/HAL/inc/sys/alt_dma.h new file mode 100644 index 0000000..9f9b2ff --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_dma.h @@ -0,0 +1,226 @@ +#ifndef __ALT_DMA_H__ +#define __ALT_DMA_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "sys/alt_dma_dev.h" +#include "alt_types.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * This header contains the application side interface for accessing DMA + * resources. See alt_dma_dev.h for the dma device driver interface. + * + * The interface model treats a DMA transaction as being composed of two + * halves (read and write). + * + * The application can supply data for transmit using an "alt_dma_txchan" + * descriptor. Alternatively an "alt_dma_rxchan" descriptor can be used to + * receive data. + */ + +/* + * alt_dma_txchan_open() is used to obtain an "alt_dma_txchan" descriptor for + * a DMA transmit device. The name is the name of the associated physical + * device (e.g. "/dev/dma_0"). + * + * The return value will be NULL on failure, and non-NULL otherwise. + */ + +extern alt_dma_txchan alt_dma_txchan_open (const char* name); + +/* + * alt_dma_txchan_close() is provided so that an application can notify the + * system that it has finished with a given DMA transmit channel. This is only + * provided for completness. + */ + +static ALT_INLINE int alt_dma_txchan_close (alt_dma_txchan dma) +{ + return 0; +} + +/* + * alt_dma_txchan_send() posts a transmit request to a DMA transmit channel. + * The input arguments are: + * + * dma: the channel to use. + * from: a pointer to the start of the data to send. + * length: the length of the data to send in bytes. + * done: callback function that will be called once the data has been sent. + * handle: opaque value passed to "done". + * + * The return value will be negative if the request cannot be posted, and + * zero otherwise. + */ + +static ALT_INLINE int alt_dma_txchan_send (alt_dma_txchan dma, + const void* from, + alt_u32 length, + alt_txchan_done* done, + void* handle) +{ + return dma ? dma->dma_send (dma, + from, + length, + done, + handle) : -ENODEV; +} + +/* + * alt_dma_txchan_space() returns the number of tranmit requests that can be + * posted to the specified DMA transmit channel. + * + * A negative value indicates that the value could not be determined. + */ + +static ALT_INLINE int alt_dma_txchan_space (alt_dma_txchan dma) +{ + return dma ? dma->space (dma) : -ENODEV; +} + +/* + * alt_dma_txchan_ioctl() can be used to perform device specific I/O + * operations on the indicated DMA transmit channel. For example some drivers + * support options to control the width of the transfer operations. See + * alt_dma_dev.h for the list of generic requests. + * + * A negative return value indicates failure, otherwise the interpretation + * of the return value is request specific. + */ + +static ALT_INLINE int alt_dma_txchan_ioctl (alt_dma_txchan dma, + int req, + void* arg) +{ + return dma ? dma->ioctl (dma, req, arg) : -ENODEV; +} + +/* + * alt_dma_rxchan_open() is used to obtain an "alt_dma_rxchan" descriptor for + * a DMA receive channel. The name is the name of the associated physical + * device (e.g. "/dev/dma_0"). + * + * The return value will be NULL on failure, and non-NULL otherwise. + */ + +extern alt_dma_rxchan alt_dma_rxchan_open (const char* dev); + +/* + * alt_dma_rxchan_close() is provided so that an application can notify the + * system that it has finished with a given DMA receive channel. This is only + * provided for completness. + */ + +static ALT_INLINE int alt_dma_rxchan_close (alt_dma_rxchan dma) +{ + return 0; +} + +/* + * + */ + +/* + * alt_dma_rxchan_prepare() posts a receive request to a DMA receive channel. + * + * The input arguments are: + * + * dma: the channel to use. + * data: a pointer to the location that data is to be received to. + * len: the maximum length of the data to receive. + * done: callback function that will be called once the data has been + * received. + * handle: opaque value passed to "done". + * + * The return value will be negative if the request cannot be posted, and + * zero otherwise. + */ + +static ALT_INLINE int alt_dma_rxchan_prepare (alt_dma_rxchan dma, + void* data, + alt_u32 len, + alt_rxchan_done* done, + void* handle) +{ + return dma ? dma->prepare (dma, data, len, done, handle) : -ENODEV; +} + +/* + * alt_dma_rxchan_ioctl() can be used to perform device specific I/O + * operations on the indicated DMA receive channel. For example some drivers + * support options to control the width of the transfer operations. See + * alt_dma_dev.h for the list of generic requests. + * + * A negative return value indicates failure, otherwise the interpretation + * of the return value is request specific. + */ + +static ALT_INLINE int alt_dma_rxchan_ioctl (alt_dma_rxchan dma, + int req, + void* arg) +{ + return dma ? dma->ioctl (dma, req, arg) : -ENODEV; +} + +/* + * alt_dma_rxchan_depth() returns the depth of the receive FIFO used to store + * receive requests. + */ + +static ALT_INLINE alt_u32 alt_dma_rxchan_depth(alt_dma_rxchan dma) +{ + return dma->depth; +} + +/* + * + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_DMA_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_dma_dev.h b/software/sys_controller_bsp/HAL/inc/sys/alt_dma_dev.h new file mode 100644 index 0000000..832463d --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_dma_dev.h @@ -0,0 +1,200 @@ +#ifndef __ALT_DMA_DEV_H__ +#define __ALT_DMA_DEV_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "priv/alt_dev_llist.h" + +#include "alt_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * This header contains the device driver interface for accessing DMA + * resources. See alt_dma.h for the DMA application side interface. + * + * The interface model treats a DMA transaction as being composed of two + * halves (read and write). + * + * An "alt_dma_txchan_dev" is used to describe the device associated with a + * DMA transmit channel. An "alt_dma_rxchan_dev" is used to describe the + * device associated with a DMA receive channel. + */ + +/* + * List of generic ioctl requests that may be supported by a DMA device. + * + * ALT_DMA_RX_ONLY_ON: This causes a DMA channel to operate in a mode + * where only the receiver is under software control. + * The other side reads continously from a single + * location. The address to read is the argument to + * this request. + * ALT_DMA_RX_ONLY_OFF: Return to the default mode where both the receive + * and transmit sides of the DMA can be under software + * control. + * ALT_DMA_TX_ONLY_ON: This causes a DMA channel to operate in a mode + * where only the transmitter is under software control. + * The other side writes continously to a single + * location. The address to write to is the argument to + * this request. + * ALT_DMA_TX_ONLY_OFF: Return to the default mode where both the receive + * and transmit sides of the DMA can be under software + * control. + * ALT_DMA_SET_MODE_8: Transfer data in units of 8 bits. + * ALT_DMA_SET_MODE_16: Transfer data in units of 16 bits. + * ALT_DMA_SET_MODE_32: Transfer data in units of 32 bits. + * ALT_DMA_SET_MODE_64: Transfer data in units of 64 bits. + * ALT_DMA_SET_MODE_128: Transfer data in units of 128 bits. + * ALT_DMA_GET_MODE: Get the current transfer mode. + * + * The use of the macros: ALT_DMA_TX_STREAM_ON, ALT_DMA_TX_STREAM_OFF + * ALT_DMA_RX_STREAM_OFF and ALT_DMA_RX_STREAM_ON are depreciated. You should + * instead use the macros: ALT_DMA_RX_ONLY_ON, ALT_DMA_RX_ONLY_OFF, + * ALT_DMA_TX_ONLY_ON and ALT_DMA_TX_ONLY_OFF. + */ + +#define ALT_DMA_TX_STREAM_ON (0x1) +#define ALT_DMA_TX_STREAM_OFF (0x2) +#define ALT_DMA_RX_STREAM_ON (0x3) +#define ALT_DMA_RX_STREAM_OFF (0x4) +#define ALT_DMA_SET_MODE_8 (0x5) +#define ALT_DMA_SET_MODE_16 (0x6) +#define ALT_DMA_SET_MODE_32 (0x7) +#define ALT_DMA_SET_MODE_64 (0x8) +#define ALT_DMA_SET_MODE_128 (0x9) +#define ALT_DMA_GET_MODE (0xa) + +#define ALT_DMA_RX_ONLY_ON ALT_DMA_TX_STREAM_ON +#define ALT_DMA_RX_ONLY_OFF ALT_DMA_TX_STREAM_OFF +#define ALT_DMA_TX_ONLY_ON ALT_DMA_RX_STREAM_ON +#define ALT_DMA_TX_ONLY_OFF ALT_DMA_RX_STREAM_OFF + +/* + * + */ + +typedef struct alt_dma_txchan_dev_s alt_dma_txchan_dev; +typedef struct alt_dma_rxchan_dev_s alt_dma_rxchan_dev; + +typedef alt_dma_txchan_dev* alt_dma_txchan; +typedef alt_dma_rxchan_dev* alt_dma_rxchan; + +typedef void (alt_txchan_done)(void* handle); +typedef void (alt_rxchan_done)(void* handle, void* data); + +/* + * devices that provide a DMA transmit channel are required to provide an + * instance of the "alt_dma_txchan_dev" structure. + */ + +struct alt_dma_txchan_dev_s { + alt_llist llist; /* for internal use */ + const char* name; /* name of the device instance + * (e.g. "/dev/dma_0"). + */ + int (*space) (alt_dma_txchan dma); /* returns the maximum number of + * transmit requests that can be posted + */ + int (*dma_send) (alt_dma_txchan dma, + const void* from, + alt_u32 len, + alt_txchan_done* done, + void* handle); /* post a transmit request */ + int (*ioctl) (alt_dma_txchan dma, int req, void* arg); /* perform device + * specific I/O control. + */ +}; + +/* + * devices that provide a DMA receive channel are required to provide an + * instance of the "alt_dma_rxchan_dev" structure. + */ + +struct alt_dma_rxchan_dev_s { + alt_llist list; /* for internal use */ + const char* name; /* name of the device instance + * (e.g. "/dev/dma_0"). + */ + alt_u32 depth; /* maximum number of receive requests that + * can be posted. + */ + int (*prepare) (alt_dma_rxchan dma, + void* data, + alt_u32 len, + alt_rxchan_done* done, + void* handle); /* post a receive request */ + int (*ioctl) (alt_dma_rxchan dma, int req, void* arg); /* perform device + * specific I/O control. + */ +}; + +/* + * Register a DMA transmit channel with the system. + */ + +static ALT_INLINE int alt_dma_txchan_reg (alt_dma_txchan_dev* dev) +{ + extern alt_llist alt_dma_txchan_list; + + return alt_dev_llist_insert((alt_dev_llist*) dev, &alt_dma_txchan_list); +} + +/* + * Register a DMA receive channel with the system. + */ + +static ALT_INLINE int alt_dma_rxchan_reg (alt_dma_rxchan_dev* dev) +{ + extern alt_llist alt_dma_rxchan_list; + + return alt_dev_llist_insert((alt_dev_llist*) dev, &alt_dma_rxchan_list); +} + +/* + * + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_DMA_DEV_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_driver.h b/software/sys_controller_bsp/HAL/inc/sys/alt_driver.h new file mode 100644 index 0000000..eb0f23b --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_driver.h @@ -0,0 +1,168 @@ +#ifndef __ALT_DRIVER_H__ +#define __ALT_DRIVER_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/* + * Macros used to access a driver without HAL file descriptors. + */ + +/* + * ALT_MODULE_CLASS + * + * This macro returns the module class name for the specified module instance. + * It uses information in the system.h file. + * Neither the instance name or class name are quoted (so that they can + * be used with other pre-processor macros). + * + * Example: + * Assume the design has an instance of an altera_avalon_uart called uart1. + * Calling ALT_MODULE_CLASS(uart1) returns altera_avalon_uart. + */ + +#define ALT_MODULE_CLASS(instance) ALT_MODULE_CLASS_ ## instance + + +/* + * ALT_DRIVER_FUNC_NAME + * + * --> instance Instance name. + * --> func Function name. + * + * This macro returns the device driver function name of the specified + * module instance for the specified function name. + * + * Example: + * Assume the design has an instance of an altera_avalon_uart called uart1. + * Calling ALT_DRIVER_FUNC_NAME(uart1, write) returns + * altera_avalon_uart_write. + */ + +#define ALT_DRIVER_FUNC_NAME(instance, func) \ + ALT_DRIVER_FUNC_NAME1(ALT_MODULE_CLASS(instance), func) +#define ALT_DRIVER_FUNC_NAME1(module_class, func) \ + ALT_DRIVER_FUNC_NAME2(module_class, func) +#define ALT_DRIVER_FUNC_NAME2(module_class, func) \ + module_class ## _ ## func + +/* + * ALT_DRIVER_STATE_STRUCT + * + * --> instance Instance name. + * + * This macro returns the device driver state type name of the specified + * module instance. + * + * Example: + * Assume the design has an instance of an altera_avalon_uart called uart1. + * Calling ALT_DRIVER_STATE_STRUCT(uart1) returns: + * struct altera_avalon_uart_state_s + * + * Note that the ALT_DRIVER_FUNC_NAME macro is used even though "state" isn't + * really a function but it does match the required naming convention. + */ +#define ALT_DRIVER_STATE_STRUCT(instance) \ + struct ALT_DRIVER_FUNC_NAME(instance, state_s) + +/* + * ALT_DRIVER_STATE + * + * --> instance Instance name. + * + * This macro returns the device driver state name of the specified + * module instance. + * + * Example: + * Assume the design has an instance of an altera_avalon_uart called uart1. + * Calling ALT_DRIVER_STATE(uart1) returns uart1. + */ +#define ALT_DRIVER_STATE(instance) instance + +/* + * ALT_DRIVER_WRITE + * + * --> instance Instance name. + * --> buffer Write buffer. + * --> len Length of write buffer data. + * --> flags Control flags (e.g. O_NONBLOCK) + * + * This macro calls the "write" function of the specified driver instance. + */ + +#define ALT_DRIVER_WRITE_EXTERNS(instance) \ + extern ALT_DRIVER_STATE_STRUCT(instance) ALT_DRIVER_STATE(instance); \ + extern int ALT_DRIVER_FUNC_NAME(instance, write) \ + (ALT_DRIVER_STATE_STRUCT(instance) *, const char *, int, int); + +#define ALT_DRIVER_WRITE(instance, buffer, len, flags) \ + ALT_DRIVER_FUNC_NAME(instance, write)(&ALT_DRIVER_STATE(instance), buffer, len, flags) + + +/* + * ALT_DRIVER_READ + * + * --> instance Instance name. + * <-- buffer Read buffer. + * --> len Length of read buffer. + * --> flags Control flags (e.g. O_NONBLOCK) + * + * This macro calls the "read" function of the specified driver instance. + */ + +#define ALT_DRIVER_READ_EXTERNS(instance) \ + extern ALT_DRIVER_STATE_STRUCT(instance) ALT_DRIVER_STATE(instance); \ + extern int ALT_DRIVER_FUNC_NAME(instance, read) \ + (ALT_DRIVER_STATE_STRUCT(instance) *, const char *, int, int); + +#define ALT_DRIVER_READ(instance, buffer, len, flags) \ + ALT_DRIVER_FUNC_NAME(instance, read)(&ALT_DRIVER_STATE(instance), buffer, len, flags) + +/* + * ALT_DRIVER_IOCTL + * + * --> instance Instance name. + * --> req ioctl request (e.g. TIOCSTIMEOUT) + * --> arg Optional argument (void*) + * + * This macro calls the "ioctl" function of the specified driver instance + */ + +#define ALT_DRIVER_IOCTL_EXTERNS(instance) \ + extern ALT_DRIVER_STATE_STRUCT(instance) ALT_DRIVER_STATE(instance); \ + extern int ALT_DRIVER_FUNC_NAME(instance, ioctl) \ + (ALT_DRIVER_STATE_STRUCT(instance) *, int, void*); + +#define ALT_DRIVER_IOCTL(instance, req, arg) \ + ALT_DRIVER_FUNC_NAME(instance, ioctl)(&ALT_DRIVER_STATE(instance), req, arg) + +#endif /* __ALT_DRIVER_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_errno.h b/software/sys_controller_bsp/HAL/inc/sys/alt_errno.h new file mode 100644 index 0000000..4d3e50f --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_errno.h @@ -0,0 +1,87 @@ +#ifndef __ALT_ERRNO_H__ +#define __ALT_ERRNO_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * errno is defined in so that it uses the thread local version + * stored in the location pointed to by "_impure_ptr". This means that the + * accesses to errno within the HAL library can cause the entirety of + * of the structure pointed to by "_impure_ptr" to be added to the + * users application. This can be undesirable in very small footprint systems. + * + * To avoid this happening, the HAL uses the macro ALT_ERRNO, defined below, + * to access errno, rather than accessing it directly. This macro will only + * use the thread local version if some other code has already caused it to be + * included into the system, otherwise it will use the global errno value. + * + * This causes a slight increases in code size where errno is accessed, but + * can lead to significant overall benefits in very small systems. The + * increase is inconsequential when compared to the size of the structure + * pointed to by _impure_ptr. + * + * Note that this macro accesses __errno() using an externally declared + * function pointer (alt_errno). This is done so that the function call uses the + * subroutine call instruction via a register rather than an immediate address. + * This is important in the case that the code has been linked for a high + * address, but __errno() is not being used. In this case the weak linkage + * would have resulted in the instruction: "call 0" which would fail to link. + */ + +extern int* (*alt_errno) (void); + +/* Must define this so that values such as EBADFD are defined in errno.h. */ +#define __LINUX_ERRNO_EXTENSIONS__ + +#include + +#include "alt_types.h" + +#undef errno + +extern int errno; + +static ALT_INLINE int* alt_get_errno(void) +{ + return ((alt_errno) ? alt_errno() : &errno); +} + +#define ALT_ERRNO *alt_get_errno() + +#endif /* __ALT_ERRNO_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_exceptions.h b/software/sys_controller_bsp/HAL/inc/sys/alt_exceptions.h new file mode 100644 index 0000000..da31ca5 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_exceptions.h @@ -0,0 +1,166 @@ +#ifndef __ALT_EXCEPTIONS_H__ +#define __ALT_EXCEPTIONS_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ +#include "alt_types.h" +#include "system.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * This file defines instruction-generated exception handling and registry + * API, exception type enumeration, and handler return value enumeration for + * Nios II. + */ + +/* + * The following enumeration describes the value in the CPU EXCEPTION + * register CAUSE bit field. + */ +enum alt_exception_cause_e { + /* + * This value is passed to an exception handler's cause argument if + * "extra exceptions" information (EXECPTION) register is not + * present in the processor hardware configuration. + */ + NIOS2_EXCEPTION_CAUSE_NOT_PRESENT = -1, + + /* + * Real values + */ + NIOS2_EXCEPTION_RESET = 0, + NIOS2_EXCEPTION_CPU_ONLY_RESET_REQUEST = 1, + NIOS2_EXCEPTION_INTERRUPT = 2, + NIOS2_EXCEPTION_TRAP_INST = 3, + NIOS2_EXCEPTION_UNIMPLEMENTED_INST = 4, + NIOS2_EXCEPTION_ILLEGAL_INST = 5, + NIOS2_EXCEPTION_MISALIGNED_DATA_ADDR = 6, + NIOS2_EXCEPTION_MISALIGNED_TARGET_PC = 7, + NIOS2_EXCEPTION_DIVISION_ERROR = 8, + NIOS2_EXCEPTION_SUPERVISOR_ONLY_INST_ADDR = 9, + NIOS2_EXCEPTION_SUPERVISOR_ONLY_INST = 10, + NIOS2_EXCEPTION_SUPERVISOR_ONLY_DATA_ADDR = 11, + NIOS2_EXCEPTION_TLB_MISS = 12, + NIOS2_EXCEPTION_TLB_EXECUTE_PERM_VIOLATION = 13, + NIOS2_EXCEPTION_TLB_READ_PERM_VIOLATION = 14, + NIOS2_EXCEPTION_TLB_WRITE_PERM_VIOLATION = 15, + NIOS2_EXCEPTION_MPU_INST_REGION_VIOLATION = 16, + NIOS2_EXCEPTION_MPU_DATA_REGION_VIOLATION = 17, + NIOS2_EXCEPTION_ECC_TLB_ERR = 18, + NIOS2_EXCEPTION_ECC_FETCH_ERR = 19, + NIOS2_EXCEPTION_ECC_REGISTER_FILE_ERR = 20, + NIOS2_EXCEPTION_ECC_DATA_ERR = 21, + NIOS2_EXCEPTION_ECC_DATA_CACHE_WRITEBACK_ERR = 22 +}; +typedef enum alt_exception_cause_e alt_exception_cause; + +/* + * These define valid return values for a user-defined instruction-generated + * exception handler. The handler should return one of these to indicate + * whether to re-issue the instruction that triggered the exception, or to + * skip it. + */ +enum alt_exception_result_e { + NIOS2_EXCEPTION_RETURN_REISSUE_INST = 0, + NIOS2_EXCEPTION_RETURN_SKIP_INST = 1 +}; +typedef enum alt_exception_result_e alt_exception_result; + +/* + * alt_instruction_exception_register() can be used to register an exception + * handler for instruction-generated exceptions that are not handled by the + * built-in exception handler (i.e. for interrupts). + * + * The registry API is optionally enabled through the "Enable + * Instruction-related Exception API" HAL BSP setting, which will + * define the macro below. + */ +#ifdef ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API +void alt_instruction_exception_register ( + alt_exception_result (*exception_handler)( + alt_exception_cause cause, + alt_u32 exception_pc, + alt_u32 bad_addr) ); +#endif /*ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API */ + +/* + * alt_exception_cause_generated_bad_addr() indicates whether a particular + * exception cause value was from an exception-type that generated a valid + * address in the BADADDR register. The contents of BADADDR is passed to + * a user-registered exception handler in all cases, whether valid or not. + * This routine should be called to validate the bad_addr argument to + * your exception handler. + * + * Note that this routine will return false (0) for causes + * NIOS2_EXCEPTION_TLB_MISS and NIOS2_EXCEPTION_ECC_TLB_ERR. + * You must read the TLBMISC.D field to determine if BADADDR + * is valid for these (valid if TLBMISC.D = 1). + */ +int alt_exception_cause_generated_bad_addr(alt_exception_cause cause); + +/* + * alt_ecc_fatal_exception_register() is called to register a handler to + * service likely fatal ECC error exceptions. Likely the handler will + * assume that correct execution of the running software is not possible + * and re-initialize the processor (e.g. jump to reset address). + * + * Passing null (0x0) in the handler argument will disable a previously- + * registered handler. + * + * Note that if no handler is registered, just normal exception processing + * occurs on a likely fatal ECC exception and the exception processing + * code might trigger an infinite exception loop. + * + * Note that the handler isn't a C function: it must be written in + * assembly-code because it doesn't support C language calling conventions + * and it can't return. + * + * The handler code must be carefully written to avoid triggering + * another fatal ECC exception and creating an infinite exception loop. + * The handler must avoid reading registers in case the fatal ECC + * error is a register file ECC error. + * If a data cache is present, the handler must avoid instructions that + * access the data cache in case the fatal ECC error is a data cache + * related ECC error. This includes cacheable load, cacheable store, + * non-cacheable store (because it looks in the data cache to update the + * data cache if it hits), and all data cache management instructions except + * for INITD. + */ +void alt_ecc_fatal_exception_register(alt_u32 handler); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_EXCEPTIONS_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_flash.h b/software/sys_controller_bsp/HAL/inc/sys/alt_flash.h new file mode 100644 index 0000000..70ed7ca --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_flash.h @@ -0,0 +1,179 @@ +#ifndef __ALT_FLASH_H__ +#define __ALT_FLASH_H__ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/****************************************************************************** +* * +* Alt_flash.h - User interface for flash code * +* * +* Use this interface to avoid being exposed to the internals of the device * +* driver architecture. If you chose to use the flash driver internal * +* structures we don't guarantee not to change them * +* * +* Author PRR * +* * +******************************************************************************/ + + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "alt_types.h" +#include "alt_flash_types.h" +#include "alt_flash_dev.h" +#include "sys/alt_cache.h" + +alt_flash_fd* alt_flash_open_dev(const char* name); +void alt_flash_close_dev(alt_flash_fd* fd ); + +/* + * alt_flash_lock + * + * Locks the range of the memory sectors, which + * protected from write and erase. + * + */ +static __inline__ int __attribute__ ((always_inline)) alt_lock_flash( + alt_flash_fd* fd, alt_u32 sectors_to_lock) +{ + return fd->lock( fd, sectors_to_lock); +} + +/* + * alt_write_flash + * + * Program a buffer into flash. + * + * This routine erases all the affected erase blocks (if necessary) + * and then programs the data. However it does not read the data out first + * and preserve and none overwritten data, because this would require very + * large buffers on the target. If you need + * that functionality use the functions below. + */ +static __inline__ int __attribute__ ((always_inline)) alt_write_flash( + alt_flash_fd* fd, + int offset, + const void* src_addr, + int length ) +{ + return fd->write( fd, offset, src_addr, length ); +} + +/* + * alt_read_flash + * + * Read a block of flash for most flashes this is just memcpy + * it's here for completeness in case we need it for some serial flash device + * + */ +static __inline__ int __attribute__ ((always_inline)) alt_read_flash( + alt_flash_fd* fd, int offset, + void* dest_addr, int length ) +{ + return fd->read( fd, offset, dest_addr, length ); +} + +/* + * alt_get_flash_info + * + * Return the information on the flash sectors. + * + */ +static __inline__ int __attribute__ ((always_inline)) alt_get_flash_info( + alt_flash_fd* fd, flash_region** info, + int* number_of_regions) +{ + return fd->get_info( fd, info, number_of_regions); +} + +/* + * alt_erase_flash_block + * + * Erase a particular erase block, pass in the offset to the start of + * the block and it's size + */ +static __inline__ int __attribute__ ((always_inline)) alt_erase_flash_block( + alt_flash_fd* fd, int offset, int length) +{ + int ret_code; + ret_code = fd->erase_block( fd, offset ); + + if(!ret_code) + alt_dcache_flush((alt_u8*)fd->base_addr + offset, length); + + return ret_code; +} + +/* + * alt_write_flash_block + * + * Write a particular flash block, block_offset is the offset + * (from the base of flash) to start of the block + * data_offset is the offset (from the base of flash) + * where you wish to start programming + * + * NB this function DOES NOT check that you are only writing a single + * block of data as that would slow down this function. + * + * Use alt_write_flash if you want that level of error checking. + */ + +static __inline__ int __attribute__ ((always_inline)) alt_write_flash_block( + alt_flash_fd* fd, int block_offset, + int data_offset, + const void *data, int length) +{ + + int ret_code; + ret_code = fd->write_block( fd, block_offset, data_offset, data, length ); + + if(!ret_code) + alt_dcache_flush((alt_u8*)fd->base_addr + data_offset, length); + + return ret_code; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_FLASH_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_flash_dev.h b/software/sys_controller_bsp/HAL/inc/sys/alt_flash_dev.h new file mode 100644 index 0000000..23c7404 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_flash_dev.h @@ -0,0 +1,100 @@ +#ifndef __ALT_FLASH_DEV_H__ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/****************************************************************************** +* * +* Alt_flash_dev.h - Generic Flash device interfaces * +* * +* Author PRR * +* * +******************************************************************************/ +#define __ALT_FLASH_DEV_H__ + +#include "alt_flash_types.h" +#include "sys/alt_llist.h" +#include "priv/alt_dev_llist.h" + +#include "alt_types.h" + +typedef struct alt_flash_dev alt_flash_dev; +typedef alt_flash_dev alt_flash_fd; + +static ALT_INLINE int alt_flash_device_register( alt_flash_fd* fd) +{ + extern alt_llist alt_flash_dev_list; + + return alt_dev_llist_insert ((alt_dev_llist*) fd, &alt_flash_dev_list); +} + +typedef alt_flash_dev* (*alt_flash_open)(alt_flash_dev* flash, + const char* name ); +typedef int (*alt_flash_close)(alt_flash_dev* flash_info); + +typedef int (*alt_flash_write)( alt_flash_dev* flash, int offset, + const void* src_addr, int length ); + +typedef int (*alt_flash_get_flash_info)( alt_flash_dev* flash, flash_region** info, + int* number_of_regions); +typedef int (*alt_flash_write_block)( alt_flash_dev* flash, int block_offset, + int data_offset, const void* data, + int length); +typedef int (*alt_flash_erase_block)( alt_flash_dev* flash, int offset); +typedef int (*alt_flash_read)(alt_flash_dev* flash, int offset, + void* dest_addr, int length ); +typedef int (*alt_flash_lock)(alt_flash_dev* flash, alt_u32 sectors_to_lock); + +struct alt_flash_dev +{ + alt_llist llist; + const char* name; + alt_flash_open open; + alt_flash_close close; + alt_flash_write write; + alt_flash_read read; + alt_flash_get_flash_info get_info; + alt_flash_erase_block erase_block; + alt_flash_write_block write_block; + void* base_addr; + int length; + int number_of_regions; + flash_region region_info[ALT_MAX_NUMBER_OF_FLASH_REGIONS]; + alt_flash_lock lock; +}; + +#endif /* __ALT_FLASH_DEV_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_flash_types.h b/software/sys_controller_bsp/HAL/inc/sys/alt_flash_types.h new file mode 100644 index 0000000..884cbf8 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_flash_types.h @@ -0,0 +1,64 @@ +#ifndef __ALT_FLASH_TYPES_H__ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/****************************************************************************** +* * +* Alt_flash_types.h - Some generic types and defines used by the flash code * +* * +* Author PRR * +* * +******************************************************************************/ +#define __ALT_FLASH_TYPES_H__ + +#ifndef ALT_MAX_NUMBER_OF_FLASH_REGIONS +#define ALT_MAX_NUMBER_OF_FLASH_REGIONS 8 +#endif /* ALT_MAX_NUMBER_OF_FLASH_REGIONS */ + +/* + * Description of a single Erase region + */ +typedef struct flash_region +{ + int offset; + int region_size; + int number_of_blocks; + int block_size; +}flash_region; + +#endif /* __ALT_FLASH_TYPES_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_irq.h b/software/sys_controller_bsp/HAL/inc/sys/alt_irq.h new file mode 100644 index 0000000..5371fc4 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_irq.h @@ -0,0 +1,245 @@ +#ifndef __ALT_IRQ_H__ +#define __ALT_IRQ_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * alt_irq.h is the Nios II specific implementation of the interrupt controller + * interface. + * + * Nios II includes optional support for an external interrupt controller. + * When an external controller is present, the "Enhanced" interrupt API + * must be used to manage individual interrupts. The enhanced API also + * supports the processor's internal interrupt controller. Certain API + * members are accessible from either the "legacy" or "enhanced" interrpt + * API. + * + * Regardless of which API is in use, this file should be included by + * application code and device drivers that register ISRs or manage interrpts. + */ +#include + +#include "nios2.h" +#include "alt_types.h" +#include "system.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Macros used by alt_irq_enabled + */ +#define ALT_IRQ_ENABLED 1 +#define ALT_IRQ_DISABLED 0 + +/* + * Number of available interrupts in internal interrupt controller. + */ +#define ALT_NIRQ NIOS2_NIRQ + +/* + * Used by alt_irq_disable_all() and alt_irq_enable_all(). + */ +typedef int alt_irq_context; + +/* ISR Prototype */ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT +typedef void (*alt_isr_func)(void* isr_context); +#else +typedef void (*alt_isr_func)(void* isr_context, alt_u32 id); +#endif + +/* + * The following protypes and routines are supported by both + * the enhanced and legacy interrupt APIs + */ + +/* + * alt_irq_enabled can be called to determine if the processor's global + * interrupt enable is asserted. The return value is zero if interrupts + * are disabled, and non-zero otherwise. + * + * Whether the internal or external interrupt controller is present, + * individual interrupts may still be disabled. Use the other API to query + * a specific interrupt. + */ +static ALT_INLINE int ALT_ALWAYS_INLINE alt_irq_enabled (void) +{ + int status; + + NIOS2_READ_STATUS (status); + + return status & NIOS2_STATUS_PIE_MSK; +} + +/* + * alt_irq_disable_all() + * + * This routine inhibits all interrupts by negating the status register PIE + * bit. It returns the previous contents of the CPU status register (IRQ + * context) which can be used to restore the status register PIE bit to its + * state before this routine was called. + */ +static ALT_INLINE alt_irq_context ALT_ALWAYS_INLINE + alt_irq_disable_all (void) +{ + alt_irq_context context; + + NIOS2_READ_STATUS (context); + + NIOS2_WRITE_STATUS (context & ~NIOS2_STATUS_PIE_MSK); + + return context; +} + +/* + * alt_irq_enable_all() + * + * Enable all interrupts that were previously disabled by alt_irq_disable_all() + * + * This routine accepts a context to restore the CPU status register PIE bit + * to the state prior to a call to alt_irq_disable_all(). + + * In the case of nested calls to alt_irq_disable_all()/alt_irq_enable_all(), + * this means that alt_irq_enable_all() does not necessarily re-enable + * interrupts. + * + * This routine will perform a read-modify-write sequence to restore only + * status.PIE if the processor is configured with options that add additional + * writeable status register bits. These include the MMU, MPU, the enhanced + * interrupt controller port, and shadow registers. Otherwise, as a performance + * enhancement, status is overwritten with the prior context. + */ +static ALT_INLINE void ALT_ALWAYS_INLINE + alt_irq_enable_all (alt_irq_context context) +{ +#if (NIOS2_NUM_OF_SHADOW_REG_SETS > 0) || (defined NIOS2_EIC_PRESENT) || \ + (defined NIOS2_MMU_PRESENT) || (defined NIOS2_MPU_PRESENT) + alt_irq_context status; + + NIOS2_READ_STATUS (status); + + status &= ~NIOS2_STATUS_PIE_MSK; + status |= (context & NIOS2_STATUS_PIE_MSK); + + NIOS2_WRITE_STATUS (status); +#else + NIOS2_WRITE_STATUS (context); +#endif +} + +/* + * The function alt_irq_init() is defined within the auto-generated file + * alt_sys_init.c. This function calls the initilization macros for all + * interrupt controllers in the system at config time, before any other + * non-interrupt controller driver is initialized. + * + * The "base" parameter is ignored and only present for backwards-compatibility. + * It is recommended that NULL is passed in for the "base" parameter. + */ +extern void alt_irq_init (const void* base); + +/* + * alt_irq_cpu_enable_interrupts() enables the CPU to start taking interrupts. + */ +static ALT_INLINE void ALT_ALWAYS_INLINE + alt_irq_cpu_enable_interrupts (void) +{ + NIOS2_WRITE_STATUS(NIOS2_STATUS_PIE_MSK +#if defined(NIOS2_EIC_PRESENT) && (NIOS2_NUM_OF_SHADOW_REG_SETS > 0) + | NIOS2_STATUS_RSIE_MSK +#endif + ); +} + + +/* + * Prototypes for the enhanced interrupt API. + */ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT +/* + * alt_ic_isr_register() can be used to register an interrupt handler. If the + * function is succesful, then the requested interrupt will be enabled upon + * return. + */ +extern int alt_ic_isr_register(alt_u32 ic_id, + alt_u32 irq, + alt_isr_func isr, + void *isr_context, + void *flags); + +/* + * alt_ic_irq_enable() and alt_ic_irq_disable() enable/disable a specific + * interrupt by using IRQ port and interrupt controller instance. + */ +int alt_ic_irq_enable (alt_u32 ic_id, alt_u32 irq); +int alt_ic_irq_disable(alt_u32 ic_id, alt_u32 irq); + + /* + * alt_ic_irq_enabled() indicates whether a specific interrupt, as + * specified by IRQ port and interrupt controller instance is enabled. + */ +alt_u32 alt_ic_irq_enabled(alt_u32 ic_id, alt_u32 irq); + +#else +/* + * Prototypes for the legacy interrupt API. + */ +#include "priv/alt_legacy_irq.h" +#endif + + +/* + * alt_irq_pending() returns a bit list of the current pending interrupts. + * This is used by alt_irq_handler() to determine which registered interrupt + * handlers should be called. + * + * This routine is only available for the Nios II internal interrupt + * controller. + */ +#ifndef NIOS2_EIC_PRESENT +static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_irq_pending (void) +{ + alt_u32 active; + + NIOS2_READ_IPENDING (active); + + return active; +} +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_IRQ_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_irq_entry.h b/software/sys_controller_bsp/HAL/inc/sys/alt_irq_entry.h new file mode 100644 index 0000000..e2008d9 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_irq_entry.h @@ -0,0 +1,39 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * This file pulls in the IRQ entry assembler and C code, which is only + * required if there are any interruptes in the system. + */ + +__asm__( "\n\t.globl alt_irq_entry" ); + +__asm__( "\n\t.globl alt_irq_handler" ); + diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_license_reminder_ucosii.h b/software/sys_controller_bsp/HAL/inc/sys/alt_license_reminder_ucosii.h new file mode 100644 index 0000000..2fe649c --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_license_reminder_ucosii.h @@ -0,0 +1,77 @@ +#ifndef __ALT_LICENSE_REMINDER_UCOSII_H__ +#define __ALT_LICENSE_REMINDER_UCOSII_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include + +#define ALT_LICENSE_REMINDER_UCOSII_STRING \ + "============== Software License Reminder ===============\n" \ + "\n" \ + "uC/OS-II is provided in source form for FREE evaluation,\n" \ + "for educational use, or for peaceful research. If you\n" \ + "plan on using uC/OS-II in a commercial product you need\n" \ + "to contact Micrium to properly license its use in your\n" \ + "product. Micrium provides ALL the source code on the\n" \ + "Altera distribution for your convenience and to help you\n" \ + "experience uC/OS-II. The fact that the source is provided\n" \ + "does NOT mean that you can use it without paying a\n" \ + "licensing fee. Please help us continue to provide the\n" \ + "Embedded community with the finest software available.\n" \ + "Your honesty is greatly appreciated.\n" \ + "\n" \ + "Please contact:\n" \ + "\n" \ + "M I C R I U M\n" \ + "949 Crestview Circle\n" \ + "Weston, FL 33327-1848\n" \ + "U.S.A.\n" \ + "\n" \ + "Phone : +1 954 217 2036\n" \ + "FAX : +1 954 217 2037\n" \ + "WEB : www.micrium.com\n" \ + "E-mail: Sales@Micrium.com\n" \ + "\n" \ + "========================================================\n" + +#define alt_license_reminder_ucosii() puts(ALT_LICENSE_REMINDER_UCOSII_STRING) + + +#endif /* __ALT_LICENSE_REMINDER_UCOSII_H__ */ + diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_llist.h b/software/sys_controller_bsp/HAL/inc/sys/alt_llist.h new file mode 100644 index 0000000..46f81ce --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_llist.h @@ -0,0 +1,123 @@ +#ifndef __ALT_LIST_H__ +#define __ALT_LIST_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "alt_types.h" + +/* + * alt_llist.h defines structures and functions for use in manipulating linked + * lists. A list is considered to be constructed from a chain of objects of + * type alt_llist, with one object being defined to be the head element. + * + * A list is considered to be empty if it only contains the head element. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * alt_llist is the structure used to represent an element within a linked + * list. + */ + +typedef struct alt_llist_s alt_llist; + +struct alt_llist_s { + alt_llist* next; /* Pointer to the next element in the list. */ + alt_llist* previous; /* Pointer to the previous element in the list. */ +}; + +/* + * ALT_LLIST_HEAD is a macro that can be used to create the head of a new + * linked list. This is named "head". The head element is initialised to + * represent an empty list. + */ + +#define ALT_LLIST_HEAD(head) alt_llist head = {&head, &head} + +/* + * ALT_LLIST_ENTRY is a macro used to define an uninitialised linked list + * entry. This is used to reserve space in structure initialisation for + * structures that inherit form alt_llist. + */ + +#define ALT_LLIST_ENTRY {0, 0} + +/* + * alt_llist_insert() insert adds the linked list entry "entry" as the + * first entry in the linked list "list". "list" is the list head element. + */ + +static ALT_INLINE void ALT_ALWAYS_INLINE alt_llist_insert(alt_llist* list, + alt_llist* entry) +{ + entry->previous = list; + entry->next = list->next; + + list->next->previous = entry; + list->next = entry; +} + +/* + * alt_llist_remove() is called to remove an element from a linked list. The + * input argument is the element to remove. + */ + +static ALT_INLINE void ALT_ALWAYS_INLINE alt_llist_remove(alt_llist* entry) +{ + entry->next->previous = entry->previous; + entry->previous->next = entry->next; + + /* + * Set the entry to point to itself, so that any further calls to + * alt_llist_remove() are harmless. + */ + + entry->previous = entry; + entry->next = entry; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_LLIST_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_load.h b/software/sys_controller_bsp/HAL/inc/sys/alt_load.h new file mode 100644 index 0000000..432e9f2 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_load.h @@ -0,0 +1,78 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "alt_types.h" + +/* + * This macro is used to load code/data from its load address to its + * execution address for a given section. The section name is the input + * argument. Note that a leading '.' is assumed in the name. For example + * to load the section .onchip_ram, use: + * + * ALT_LOAD_SECTION_BY_NAME(onchip_ram); + * + * This requires that the apropriate linker symbols have been generated + * for the section in question. This will be the case if you are using the + * default linker script. + */ + +#define ALT_LOAD_SECTION_BY_NAME(name) \ + { \ + extern void _alt_partition_##name##_start; \ + extern void _alt_partition_##name##_end; \ + extern void _alt_partition_##name##_load_addr; \ + \ + alt_load_section(&_alt_partition_##name##_load_addr, \ + &_alt_partition_##name##_start, \ + &_alt_partition_##name##_end); \ + } + +/* + * Function used to load an individual section from flash to RAM. + * + * There is an implicit assumption here that the linker script will ensure + * that all sections are word aligned. + * + */ + +static void ALT_INLINE alt_load_section (alt_u32* from, + alt_u32* to, + alt_u32* end) +{ + if (to != from) + { + while( to != end ) + { + *to++ = *from++; + } + } +} diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_log_printf.h b/software/sys_controller_bsp/HAL/inc/sys/alt_log_printf.h new file mode 100644 index 0000000..c15ca05 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_log_printf.h @@ -0,0 +1,349 @@ +/* alt_log_printf.h + * + * ALT_LOG is designed to provide extra logging/debugging messages from HAL + * through a different port than stdout. It is enabled by the ALT_LOG_ENABLE + * define, which needs to supplied at compile time. When logging is turned off, + * code size is unaffected. Thus, this should be transparent to the user + * when it is not actively turned on, and should not affect projects in any way. + * + * There are macros sprinkled within different components, such as the jtag uart + * and timer, in the HAL code. They are always named ALT_LOG_, and can be + * safely ignored if ALT_LOG is turned off. + * + * To turn on ALT_LOG, ALT_LOG_ENABLE must be defined, and ALT_LOG_PORT_TYPE and + * ALT_LOG_PORT_BASE must be set in system.h. This is done through editing + * .ptf, by editing the alt_log_port_type & alt_log_port_base settings. + * See the documentation html file for examples. + * + * When it is turned on, it will output extra HAL messages to a port specified + * in system.h. This can be a UART or JTAG UART port. By default it will + * output boot messages, detailing every step of the boot process. + * + * Extra logging is designed to be enabled by flags, which are defined in + * alt_log_printf.c. The default value is that all flags are off, so only the + * boot up logging messages show up. ALT_LOG_FLAGS can be set to enable certain + * groupings of flags, and that grouping is done in this file. Each flag can + * also be overridden with a -D at compile time. + * + * This header file includes the necessary prototypes for using the alt_log + * functions. It also contains all the macros that are used to remove the code + * from alt log is turned off. Also, the macros in other HAL files are defined + * here at the bottom. These macros all call some C function that is in + * alt_log_printf.c. + * + * The logging has functions for printing in C (ALT_LOG_PRINTF) and in assembly + * (ALT_LOG_PUTS). This was needed because the assembly printing occurs before + * the device is initialized. The assembly function corrupts register R4-R7, + * which are not used in the normal boot process. For this reason, do not call + * the assembly function in C. + * + * author: gkwan + */ + + +#ifndef __ALT_LOG_PRINTF_H__ +#define __ALT_LOG_PRINTF_H__ + +#include + +/* Global switch to turn on logging functions */ +#ifdef ALT_LOG_ENABLE + + /* ALT_LOG_PORT_TYPE values as defined in system.h. They are defined as + * numbers here first becasue the C preprocessor does not handle string + * comparisons. */ + #define ALTERA_AVALON_JTAG_UART 1 + #define ALTERA_AVALON_UART 0 + + /* If this .h file is included by an assembly file, skip over include files + * that won't compile in assembly. */ + #ifndef ALT_ASM_SRC + #include + #include "sys/alt_alarm.h" + #include "sys/alt_dev.h" + #ifdef __ALTERA_AVALON_JTAG_UART + #include "altera_avalon_jtag_uart.h" + #endif + #endif /* ALT_ASM_SRC */ + + /* These are included for the port register offsets and masks, needed + * to write to the port. Only include if the port type is set correctly, + * otherwise error. If alt_log is turned on and the port to output to is + * incorrect or does not exist, then should exit. */ + #if ALT_LOG_PORT_TYPE == ALTERA_AVALON_JTAG_UART + #ifdef __ALTERA_AVALON_JTAG_UART + #include + #else + #error ALT_LOG: JTAG_UART port chosen, but no JTAG_UART in system. + #endif + #elif ALT_LOG_PORT_TYPE == ALTERA_AVALON_UART + #ifdef __ALTERA_AVALON_UART + #include + #else + #error ALT_LOG: UART Port chosen, but no UART in system. + #endif + #else + #error ALT_LOG: alt_log_port_type declaration invalid! + #endif + + /* ALT_LOG_ENABLE turns on the basic printing function */ + #define ALT_LOG_PRINTF(...) do {alt_log_printf_proc(__VA_ARGS__);} while (0) + + /* Assembly macro for printing in assembly, calls tx_log_str + * which is in alt_log_macro.S. + * If alt_log_boot_on_flag is 0, skips the printing */ + #define ALT_LOG_PUTS(str) movhi r4, %hiadj(alt_log_boot_on_flag) ; \ + addi r4, r4, %lo(alt_log_boot_on_flag) ; \ + ldwio r5, 0(r4) ; \ + beq r0, r5, 0f ; \ + movhi r4, %hiadj(str) ; \ + addi r4, r4, %lo(str) ; \ + call tx_log_str ; \ + 0: + + /* These defines are here to faciliate the use of one output function + * (alt_log_txchar) to print to both the JTAG UART or the UART. Depending + * on the port type, the status register, read mask, and output register + * are set to the appropriate value for the port. */ + #if ALT_LOG_PORT_TYPE == ALTERA_AVALON_JTAG_UART + #define ALT_LOG_PRINT_REG_RD IORD_ALTERA_AVALON_JTAG_UART_CONTROL + #define ALT_LOG_PRINT_MSK ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK + #define ALT_LOG_PRINT_TXDATA_WR IOWR_ALTERA_AVALON_JTAG_UART_DATA + #define ALT_LOG_PRINT_REG_OFFSET (ALTERA_AVALON_JTAG_UART_CONTROL_REG*0x4) + #define ALT_LOG_PRINT_TXDATA_REG_OFFSET (ALTERA_AVALON_JTAG_UART_DATA_REG*0x4) + #elif ALT_LOG_PORT_TYPE == ALTERA_AVALON_UART + #define ALT_LOG_PRINT_REG_RD IORD_ALTERA_AVALON_UART_STATUS + #define ALT_LOG_PRINT_MSK ALTERA_AVALON_UART_STATUS_TRDY_MSK + #define ALT_LOG_PRINT_TXDATA_WR IOWR_ALTERA_AVALON_UART_TXDATA + #define ALT_LOG_PRINT_REG_OFFSET (ALTERA_AVALON_UART_STATUS_REG*0x4) + #define ALT_LOG_PRINT_TXDATA_REG_OFFSET (ALTERA_AVALON_UART_TXDATA_REG*0x4) + #endif /* ALT_LOG_PORT */ + + /* Grouping of flags via ALT_LOG_FLAGS. Each specific flag can be set via + * -D at compile time, or else they'll be set to a default value according + * to ALT_LOG_FLAGS. ALT_LOG_FLAGS = 0 or not set is the default, where + * only the boot messages will be printed. As ALT_LOG_FLAGS increase, they + * increase in intrusiveness to the program, and will affect performance. + * + * Flag Level 1 - turns on system clock and JTAG UART startup status + * 2 - turns on write echo and JTAG_UART alarm (periodic report) + * 3 - turns on JTAG UART ISR logging - will slow performance + * significantly. + * -1 - All logging output is off, but if ALT_LOG_ENABLE is + * defined all logging function is built and code size + * remains constant + * + * Flag settings - 1 = on, 0 = off. */ + + /* This flag turns on "boot" messages for printing. This includes messages + * during crt0.S, then alt_main, and finally alt_exit. */ + #ifndef ALT_LOG_BOOT_ON_FLAG_SETTING + #if ALT_LOG_FLAGS == 1 + #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 2 + #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 3 + #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == -1 /* silent mode */ + #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x0 + #else /* default setting */ + #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1 + #endif + #endif /* ALT_LOG_BOOT_ON_FLAG_SETTING */ + + #ifndef ALT_LOG_SYS_CLK_ON_FLAG_SETTING + #if ALT_LOG_FLAGS == 1 + #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 2 + #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 3 + #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == -1 /* silent mode */ + #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x0 + #else /* default setting */ + #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x0 + #endif + #endif /* ALT_LOG_SYS_CLK_ON_FLAG_SETTING */ + + #ifndef ALT_LOG_WRITE_ON_FLAG_SETTING + #if ALT_LOG_FLAGS == 1 + #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 2 + #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 3 + #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == -1 /* silent mode */ + #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x0 + #else /* default setting */ + #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x0 + #endif + #endif /* ALT_LOG_WRITE_ON_FLAG_SETTING */ + + #ifndef ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING + #ifndef __ALTERA_AVALON_JTAG_UART + #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 1 + #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 2 + #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 3 + #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == -1 /* silent mode */ + #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0 + #else /* default setting */ + #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0 + #endif + #endif /* ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING */ + + #ifndef ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING + #ifndef __ALTERA_AVALON_JTAG_UART + #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 1 + #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 2 + #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == 3 + #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == -1 /* silent mode */ + #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x0 + #else /* default setting */ + #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x0 + #endif + #endif /* ALT_LOG_JTAG_UART_STARTUP_INFO_FLAG_SETTING */ + + #ifndef ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING + #ifndef __ALTERA_AVALON_JTAG_UART + #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 1 + #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 2 + #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0 + #elif ALT_LOG_FLAGS == 3 + #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x1 + #elif ALT_LOG_FLAGS == -1 /* silent mode */ + #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0 + #else /* default setting */ + #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0 + #endif + #endif /* ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING */ + +#ifndef ALT_ASM_SRC + /* Function Prototypes */ + void alt_log_txchar(int c,char *uartBase); + void alt_log_private_printf(const char *fmt,int base,va_list args); + void alt_log_repchar(char c,int r,int base); + int alt_log_printf_proc(const char *fmt, ... ); + void alt_log_system_clock(); + #ifdef __ALTERA_AVALON_JTAG_UART + alt_u32 altera_avalon_jtag_uart_report_log(void * context); + void alt_log_jtag_uart_startup_info(altera_avalon_jtag_uart_state* dev, int base); + void alt_log_jtag_uart_print_control_reg(altera_avalon_jtag_uart_state* dev, \ + int base, const char* header); + void alt_log_jtag_uart_isr_proc(int base, altera_avalon_jtag_uart_state* dev); + #endif + void alt_log_write(const void *ptr, size_t len); + + /* extern all global variables */ + extern volatile alt_u32 alt_log_boot_on_flag; + extern volatile alt_u8 alt_log_write_on_flag; + extern volatile alt_u8 alt_log_sys_clk_on_flag; + extern volatile alt_u8 alt_log_jtag_uart_alarm_on_flag; + extern volatile alt_u8 alt_log_jtag_uart_isr_on_flag; + extern volatile alt_u8 alt_log_jtag_uart_startup_info_on_flag; + extern volatile int alt_log_sys_clk_count; + extern volatile int alt_system_clock_in_sec; + extern alt_alarm alt_log_jtag_uart_alarm_1; +#endif /* ALT_ASM_SRC */ + + + /* Below are the MACRO defines used in various HAL files. They check + * if their specific flag is turned on; if it is, then it executes its + * code. + * + * To keep this file reasonable, most of these macros calls functions, + * which are defined in alt_log_printf.c. Look there for implementation + * details. */ + + /* Boot Messages Logging */ + #define ALT_LOG_PRINT_BOOT(...) \ + do { if (alt_log_boot_on_flag==1) {ALT_LOG_PRINTF(__VA_ARGS__);} \ + } while (0) + + /* JTAG UART Logging */ + /* number of ticks before alarm runs logging function */ + #ifndef ALT_LOG_JTAG_UART_TICKS_DIVISOR + #define ALT_LOG_JTAG_UART_TICKS_DIVISOR 10 + #endif + #ifndef ALT_LOG_JTAG_UART_TICKS + #define ALT_LOG_JTAG_UART_TICKS \ + (alt_ticks_per_second()/ALT_LOG_JTAG_UART_TICKS_DIVISOR) + #endif + + /* if there's a JTAG UART defined, then enable these macros */ + #ifdef __ALTERA_AVALON_JTAG_UART + + /* Macro in altera_avalon_jtag_uart.c, to register the alarm function. + * Also, the startup register info is also printed here, as this is + * called within the device driver initialization. */ + #define ALT_LOG_JTAG_UART_ALARM_REGISTER(dev, base) \ + do { if (alt_log_jtag_uart_alarm_on_flag==1) { \ + alt_alarm_start(&alt_log_jtag_uart_alarm_1, \ + ALT_LOG_JTAG_UART_TICKS, &altera_avalon_jtag_uart_report_log,\ + dev);} \ + if (alt_log_jtag_uart_startup_info_on_flag==1) {\ + alt_log_jtag_uart_startup_info(dev, base);} \ + } while (0) + + /* JTAG UART IRQ Logging (when buffer is empty) + * Inserted in the ISR in altera_avalon_jtag_uart.c */ + #define ALT_LOG_JTAG_UART_ISR_FUNCTION(base, dev) \ + do { alt_log_jtag_uart_isr_proc(base, dev); } while (0) + /* else, define macros to nothing. Or else the jtag_uart specific types + * will throw compiler errors */ + #else + #define ALT_LOG_JTAG_UART_ALARM_REGISTER(dev, base) + #define ALT_LOG_JTAG_UART_ISR_FUNCTION(base, dev) + #endif + + /* System clock logging + * How often (in seconds) the system clock logging prints. + * The default value is every 1 second */ + #ifndef ALT_LOG_SYS_CLK_INTERVAL_MULTIPLIER + #define ALT_LOG_SYS_CLK_INTERVAL_MULTIPLIER 1 + #endif + #ifndef ALT_LOG_SYS_CLK_INTERVAL + #define ALT_LOG_SYS_CLK_INTERVAL \ + (alt_ticks_per_second()*ALT_LOG_SYS_CLK_INTERVAL_MULTIPLIER) + #endif + + /* System clock logging - prints a message every interval (set above) + * to show that the system clock is alive. + * This macro is used in altera_avalon_timer_sc.c */ + #define ALT_LOG_SYS_CLK_HEARTBEAT() \ + do { alt_log_system_clock(); } while (0) + + /* alt_write_logging - echos a message every time write() is called, + * displays the first ALT_LOG_WRITE_ECHO_LEN characters. + * This macro is used in alt_write.c */ + #ifndef ALT_LOG_WRITE_ECHO_LEN + #define ALT_LOG_WRITE_ECHO_LEN 15 + #endif + + #define ALT_LOG_WRITE_FUNCTION(ptr,len) \ + do { alt_log_write(ptr,len); } while (0) + +#else /* ALT_LOG_ENABLE not defined */ + + /* logging is off, set all relevant macros to null */ + #define ALT_LOG_PRINT_BOOT(...) + #define ALT_LOG_PRINTF(...) + #define ALT_LOG_JTAG_UART_ISR_FUNCTION(base, dev) + #define ALT_LOG_JTAG_UART_ALARM_REGISTER(dev, base) + #define ALT_LOG_SYS_CLK_HEARTBEAT() + #define ALT_LOG_PUTS(str) + #define ALT_LOG_WRITE_FUNCTION(ptr,len) + +#endif /* ALT_LOG_ENABLE */ + +#endif /* __ALT_LOG_PRINTF_H__ */ + diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_set_args.h b/software/sys_controller_bsp/HAL/inc/sys/alt_set_args.h new file mode 100644 index 0000000..3750e67 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_set_args.h @@ -0,0 +1,71 @@ +#ifndef __ALT_SET_ARGS_H__ +#define __ALT_SET_ARGS_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The function alt_set_args() is provided in order to define the input + * arguments to main(). If this function is not called before main() then the + * argument list passed to main() will be empty. + * + * It is expected that this function will only be used by the ihost/iclient + * utility. + */ + +static inline void alt_set_args (int argc, char** argv, char** envp) +{ + extern int alt_argc; + extern char** alt_argv; + extern char** alt_envp; + + alt_argc = argc; + alt_argv = argv; + alt_envp = envp; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_SET_ARGS_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_sim.h b/software/sys_controller_bsp/HAL/inc/sys/alt_sim.h new file mode 100644 index 0000000..471afa3 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_sim.h @@ -0,0 +1,91 @@ +#ifndef __ALT_SIM_H__ +#define __ALT_SIM_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ +#include "system.h" +#include "alt_types.h" + +/* + * Instructions that might mean something special to a simulator. + * These have no special effect on real hardware (they are just nops). + */ +#define ALT_SIM_FAIL() \ + do { __asm volatile ("cmpltui r0, r0, 0xabc1"); } while (0) + +#define ALT_SIM_PASS() \ + do { __asm volatile ("cmpltui r0, r0, 0xabc2"); } while (0) + +#define ALT_SIM_IN_TOP_OF_HOT_LOOP() \ + do { __asm volatile ("cmpltui r0, r0, 0xabc3"); } while (0) + +/* + * Routine called on exit. + */ +static ALT_INLINE ALT_ALWAYS_INLINE void alt_sim_halt(int exit_code) +{ + register int r2 asm ("r2") = exit_code; + +#if defined(NIOS2_HAS_DEBUG_STUB) && (defined(ALT_BREAK_ON_EXIT) || defined(ALT_PROVIDE_GMON)) + + register int r3 asm ("r3") = (1 << 2); + +#ifdef ALT_PROVIDE_GMON + extern unsigned int alt_gmon_data[]; + register int r4 asm ("r4") = (int)alt_gmon_data; + r3 |= (1 << 4); +#define ALT_GMON_DATA ,"r"(r4) +#else +#define ALT_GMON_DATA +#endif /* ALT_PROVIDE_GMON */ + + if (r2) { + ALT_SIM_FAIL(); + } else { + ALT_SIM_PASS(); + } + + __asm__ volatile ("\n0:\n\taddi %0,%0, -1\n\tbgt %0,zero,0b" : : "r" (ALT_CPU_FREQ/100) ); /* Delay for >30ms */ + + __asm__ volatile ("break 2" : : "r"(r2), "r"(r3) ALT_GMON_DATA ); + +#else /* !DEBUG_STUB */ + if (r2) { + ALT_SIM_FAIL(); + } else { + ALT_SIM_PASS(); + } +#endif /* DEBUG_STUB */ +} + +#define ALT_SIM_HALT(exit_code) \ + alt_sim_halt(exit_code) + +#endif /* __ALT_SIM_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_stack.h b/software/sys_controller_bsp/HAL/inc/sys/alt_stack.h new file mode 100644 index 0000000..e30652a --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_stack.h @@ -0,0 +1,126 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALT_STACK_H__ +#define __ALT_STACK_H__ + +/* + * alt_stack.h is the nios2 specific implementation of functions used by the + * stack overflow code. + */ + +#include "nios2.h" + +#include "alt_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +extern char * alt_stack_limit_value; + +#ifdef ALT_EXCEPTION_STACK +extern char __alt_exception_stack_pointer[]; /* set by the linker */ +#endif /* ALT_EXCEPTION_STACK */ + + +/* + * alt_stack_limit can be called to determine the current value of the stack + * limit register. + */ + +static ALT_INLINE char * ALT_ALWAYS_INLINE alt_stack_limit (void) +{ + char * limit; + NIOS2_READ_ET(limit); + + return limit; +} + +/* + * alt_stack_pointer can be called to determine the current value of the stack + * pointer register. + */ + +static ALT_INLINE char * ALT_ALWAYS_INLINE alt_stack_pointer (void) +{ + char * pointer; + NIOS2_READ_SP(pointer); + + return pointer; +} + + +#ifdef ALT_EXCEPTION_STACK + +/* + * alt_exception_stack_pointer returns the normal stack pointer from + * where it is stored on the exception stack (uppermost 4 bytes). This + * is really only useful during exception processing, and is only + * available if a separate exception stack has been configured. + */ + +static ALT_INLINE char * ALT_ALWAYS_INLINE alt_exception_stack_pointer (void) +{ + return (char *) *(alt_u32 *)(__alt_exception_stack_pointer - sizeof(alt_u32)); +} + +#endif /* ALT_EXCEPTION_STACK */ + + +/* + * alt_set_stack_limit can be called to update the current value of the stack + * limit register. + */ + +static ALT_INLINE void ALT_ALWAYS_INLINE alt_set_stack_limit (char * limit) +{ + alt_stack_limit_value = limit; + NIOS2_WRITE_ET(limit); +} + +/* + * alt_report_stack_overflow reports that a stack overflow happened. + */ + +static ALT_INLINE void ALT_ALWAYS_INLINE alt_report_stack_overflow (void) +{ + NIOS2_REPORT_STACK_OVERFLOW(); +} + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_STACK_H__ */ + diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_stdio.h b/software/sys_controller_bsp/HAL/inc/sys/alt_stdio.h new file mode 100644 index 0000000..f89ba90 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_stdio.h @@ -0,0 +1,66 @@ +#ifndef __ALT_STDIO_H__ +#define __ALT_STDIO_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * Definitions for ALT stdio routines. + */ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +int alt_getchar(); +int alt_putchar(int c); +int alt_putstr(const char* str); +void alt_printf(const char *fmt, ...); +#ifdef ALT_SEMIHOSTING +int alt_putcharbuf(int c); +int alt_putstrbuf(const char* str); +int alt_putbufflush(); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_STDIO_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_sys_init.h b/software/sys_controller_bsp/HAL/inc/sys/alt_sys_init.h new file mode 100644 index 0000000..e4abc28 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_sys_init.h @@ -0,0 +1,62 @@ +#ifndef __ALT_SYS_INIT_H__ +#define __ALT_SYS_INIT_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The function alt_sys_init() is defined within the auto-generated file: + * alt_sys_init.c. This function calls the initilisation macros for all + * devices, file systems, and software components within the system. + * + * The list of initilisation macros to use is constructed using the PTF and + * STF files associated with the system. + */ + +extern void alt_sys_init (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_SYS_INIT_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_sys_wrappers.h b/software/sys_controller_bsp/HAL/inc/sys/alt_sys_wrappers.h new file mode 100644 index 0000000..044833b --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_sys_wrappers.h @@ -0,0 +1,100 @@ +#ifndef __ALT_SYS_WRAPPERS_H__ +#define __ALT_SYS_WRAPPERS_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * This file provides the prototypes for the HAL 'UNIX style functions. The + * names of these functions are defined in alt_syscall.h. THese are defined to + * be the standard names when running the standalone HAL, e.g. open(), close() + * etc., but the names may be redefined as a part of an operating system port + * in order to avoid name clashes. + */ + +#include "os/alt_syscall.h" + +#include +#include +#include +#include +#include +#include + +extern int ALT_CLOSE (int __fd); +extern int ALT_EXECVE (const char *__path, + char * const __argv[], + char * const __envp[]); +extern void ALT_EXIT (int __status); +extern int ALT_FSTAT (int file, struct stat *st); +extern int ALT_FCNTL (int file, int cmd, ...); +extern pid_t ALT_FORK (void); +extern pid_t ALT_GETPID (void); + +#if defined (__GNUC__) && __GNUC__ >= 4 +extern int ALT_GETTIMEOFDAY (struct timeval *ptimeval, + void *ptimezone); +#else +extern int ALT_GETTIMEOFDAY (struct timeval *ptimeval, + struct timezone *ptimezone); +#endif + +extern int ALT_IOCTL (int file, int req, void* arg); +extern int ALT_ISATTY (int file); +extern int ALT_KILL (int pid, int sig); +extern int ALT_LINK (const char *existing, const char *new); +extern off_t ALT_LSEEK (int file, off_t ptr, int dir); +extern int ALT_OPEN (const char* file, int flags, ...); +extern int ALT_READ (int file, void *ptr, size_t len); +extern int ALT_RENAME (char *existing, char *new); +extern void* ALT_SBRK (ptrdiff_t incr); +extern int ALT_SETTIMEOFDAY (const struct timeval *t, + const struct timezone *tz); +extern int ALT_STAT (const char *file, struct stat *st); +extern clock_t ALT_TIMES (struct tms *buf); +extern int ALT_UNLINK (const char *name); + +#if defined (__GNUC__) && __GNUC__ >= 4 +int ALT_USLEEP (useconds_t us); +#else +unsigned int ALT_USLEEP (unsigned int us); +#endif + +extern int ALT_WAIT (int *status); +extern int ALT_WRITE (int file, const void *ptr, size_t len); + + +extern char** ALT_ENVIRON; + +/* + * + */ + +#endif /* __ALT_SYS_WRAPPERS_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_timestamp.h b/software/sys_controller_bsp/HAL/inc/sys/alt_timestamp.h new file mode 100644 index 0000000..8a18da2 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_timestamp.h @@ -0,0 +1,60 @@ +#ifndef __ALT_TIMESTAMP_H__ +#define __ALT_TIMESTAMP_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#include "alt_types.h" +#include "altera_avalon_timer.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +extern int alt_timestamp_start (void); + +extern alt_timestamp_type alt_timestamp (void); + +extern alt_u32 alt_timestamp_freq (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_TIMESTAMP_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/alt_warning.h b/software/sys_controller_bsp/HAL/inc/sys/alt_warning.h new file mode 100644 index 0000000..b66e71a --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/alt_warning.h @@ -0,0 +1,75 @@ +#ifndef __WARNING_H__ +#define __WARNING_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * alt_warning.h provides macro definitions that can be used to generate link + * time warnings. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The symbol "__alt_invalid" is used to force a link error. There should be + * no corresponding implementation of this function. + */ + +extern void __alt_invalid (void); + +#define ALT_LINK_WARNING(symbol, msg) \ + __asm__(".ifndef __evoke_link_warning_" #symbol \ + "\n\t .section .gnu.warning." #symbol \ + "\n__evoke_link_warning_" #symbol ":\n\t .string \x22" msg "\x22 \n\t .previous" \ + "\n .endif"); + +/* A canned warning for sysdeps/stub functions. */ + +#define ALT_STUB_WARNING(name) \ + ALT_LINK_WARNING (name, \ + "warning: " #name " is not implemented and will always fail") + +#define ALT_OBSOLETE_FUNCTION_WARNING(name) \ + ALT_LINK_WARNING (name, \ + "warning: " #name " is a deprecated function") + +#define ALT_LINK_ERROR(msg) \ + ALT_LINK_WARNING (__alt_invalid, msg); \ + __alt_invalid() + +#ifdef __cplusplus +} +#endif + +#endif /* __WARNING_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/ioctl.h b/software/sys_controller_bsp/HAL/inc/sys/ioctl.h new file mode 100644 index 0000000..4d565df --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/ioctl.h @@ -0,0 +1,90 @@ +#ifndef __IOCTL_H__ +#define __IOCTL_H__ + +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * The ioctl() system call be used to initiate a variety of control operations + * on a file descriptor. For the most part this simply translates to a call to + * the ioctl() function of the associated device driver (TIOCEXCL and + * TIOCNXCL are notable exceptions - see ioctl.c for details). + * + * The interpretation of the ioctl requests are therefore device specific. + * + * This function is equivalent to the standard Posix ioctl() call. + */ + +extern int ioctl (int fd, int req, void* arg); + +/* + * list of ioctl calls handled by the system ioctl implementation. + */ + +#define TIOCEXCL 0x740d /* exclusive use of the device */ +#define TIOCNXCL 0x740e /* allow multiple use of the device */ + +/* + * ioctl calls which can be handled by device drivers. + */ + +#define TIOCOUTQ 0x7472 /* get output queue size */ +#define TIOCMGET 0x741d /* get termios flags */ +#define TIOCMSET 0x741a /* set termios flags */ + +/* + * ioctl calls specific to JTAG UART. + */ + +#define TIOCSTIMEOUT 0x6a01 /* Set Timeout before assuming no host present */ +#define TIOCGCONNECTED 0x6a02 /* Get indication of whether host is connected */ + +/* + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __IOCTL_H__ */ diff --git a/software/sys_controller_bsp/HAL/inc/sys/termios.h b/software/sys_controller_bsp/HAL/inc/sys/termios.h new file mode 100644 index 0000000..cd09539 --- /dev/null +++ b/software/sys_controller_bsp/HAL/inc/sys/termios.h @@ -0,0 +1,181 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT. * +* * +******************************************************************************/ + +/* + * This is the termios.h file provided with newlib. The only modification has + * been to the baud rate macro definitions, and an increase in the size of the + * termios structure to accomodate this. + */ + + +#ifndef _SYS_TERMIOS_H +# define _SYS_TERMIOS_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +# define _XCGETA (('x'<<8)|1) +# define _XCSETA (('x'<<8)|2) +# define _XCSETAW (('x'<<8)|3) +# define _XCSETAF (('x'<<8)|4) +# define _TCSBRK (('T'<<8)|5) +# define _TCFLSH (('T'<<8)|7) +# define _TCXONC (('T'<<8)|6) + +# define TCOOFF 0 +# define TCOON 1 +# define TCIOFF 2 +# define TCION 3 + +# define TCIFLUSH 0 +# define TCOFLUSH 1 +# define TCIOFLUSH 2 + +# define NCCS 13 + +# define TCSAFLUSH _XCSETAF +# define TCSANOW _XCSETA +# define TCSADRAIN _XCSETAW +# define TCSADFLUSH _XCSETAF + +# define IGNBRK 000001 +# define BRKINT 000002 +# define IGNPAR 000004 +# define INPCK 000020 +# define ISTRIP 000040 +# define INLCR 000100 +# define IGNCR 000200 +# define ICRNL 000400 +# define IXON 002000 +# define IXOFF 010000 + +# define OPOST 000001 +# define OCRNL 000004 +# define ONLCR 000010 +# define ONOCR 000020 +# define TAB3 014000 + +# define CLOCAL 004000 +# define CREAD 000200 +# define CSIZE 000060 +# define CS5 0 +# define CS6 020 +# define CS7 040 +# define CS8 060 +# define CSTOPB 000100 +# define HUPCL 002000 +# define PARENB 000400 +# define PAODD 001000 + +#define CCTS_OFLOW 010000 +#define CRTS_IFLOW 020000 +#define CRTSCTS (CCTS_OFLOW | CRTS_IFLOW) + +# define ECHO 0000010 +# define ECHOE 0000020 +# define ECHOK 0000040 +# define ECHONL 0000100 +# define ICANON 0000002 +# define IEXTEN 0000400 /* anybody know *what* this does?! */ +# define ISIG 0000001 +# define NOFLSH 0000200 +# define TOSTOP 0001000 + +# define VEOF 4 /* also VMIN -- thanks, AT&T */ +# define VEOL 5 /* also VTIME -- thanks again */ +# define VERASE 2 +# define VINTR 0 +# define VKILL 3 +# define VMIN 4 /* also VEOF */ +# define VQUIT 1 +# define VSUSP 10 +# define VTIME 5 /* also VEOL */ +# define VSTART 11 +# define VSTOP 12 + +# define B0 0 +# define B50 50 +# define B75 75 +# define B110 110 +# define B134 134 +# define B150 150 +# define B200 200 +# define B300 300 +# define B600 600 +# define B1200 1200 +# define B1800 1800 +# define B2400 2400 +# define B4800 4800 +# define B9600 9600 +# define B19200 19200 +# define B38400 38400 +# define B57600 57600 +# define B115200 115200 + +typedef unsigned char cc_t; +typedef unsigned short tcflag_t; +typedef unsigned long speed_t; + +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + char c_line; + cc_t c_cc[NCCS]; + speed_t c_ispeed; + speed_t c_ospeed; +}; + +# ifndef _NO_MACROS + +# define cfgetospeed(tp) ((tp)->c_ospeed) +# define cfgetispeed(tp) ((tp)->c_ispeed) +# define cfsetospeed(tp,s) (((tp)->c_ospeed = (s)), 0) +# define cfsetispeed(tp,s) (((tp)->c_ispeed = (s)), 0) +# define tcdrain(fd) _ioctl (fd, _TCSBRK, 1) +# endif /* _NO_MACROS */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_TERMIOS_H */ + diff --git a/software/sys_controller_bsp/HAL/src/alt_alarm_start.c b/software/sys_controller_bsp/HAL/src/alt_alarm_start.c new file mode 100644 index 0000000..7739959 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_alarm_start.c @@ -0,0 +1,112 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "sys/alt_alarm.h" +#include "sys/alt_irq.h" + +/* + * alt_alarm_start is called to register an alarm with the system. The + * "alarm" structure passed as an input argument does not need to be + * initialised by the user. This is done within this function. + * + * The remaining input arguments are: + * + * nticks - The time to elapse until the alarm executes. This is specified in + * system clock ticks. + * callback - The function to run when the indicated time has elapsed. + * context - An opaque value, passed to the callback function. +* + * Care should be taken when defining the callback function since it is + * likely to execute in interrupt context. In particular, this mean that + * library calls like printf() should not be made, since they can result in + * deadlock. + * + * The interval to be used for the next callback is the return + * value from the callback function. A return value of zero indicates that the + * alarm should be unregistered. + * + * alt_alarm_start() will fail if the timer facility has not been enabled + * (i.e. there is no system clock). Failure is indicated by a negative return + * value. + */ + +int alt_alarm_start (alt_alarm* alarm, alt_u32 nticks, + alt_u32 (*callback) (void* context), + void* context) +{ + alt_irq_context irq_context; + alt_u32 current_nticks = 0; + + if (alt_ticks_per_second ()) + { + if (alarm) + { + alarm->callback = callback; + alarm->context = context; + + irq_context = alt_irq_disable_all (); + + current_nticks = alt_nticks(); + + alarm->time = nticks + current_nticks + 1; + + /* + * If the desired alarm time causes a roll-over, set the rollover + * flag. This will prevent the subsequent tick event from causing + * an alarm too early. + */ + if(alarm->time < current_nticks) + { + alarm->rollover = 1; + } + else + { + alarm->rollover = 0; + } + + alt_llist_insert (&alt_alarm_list, &alarm->llist); + alt_irq_enable_all (irq_context); + + return 0; + } + else + { + return -EINVAL; + } + } + else + { + return -ENOTSUP; + } +} diff --git a/software/sys_controller_bsp/HAL/src/alt_busy_sleep.c b/software/sys_controller_bsp/HAL/src/alt_busy_sleep.c new file mode 100644 index 0000000..561c0be --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_busy_sleep.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003-2004 Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * ------------ + * + * Altera does not recommend, suggest or require that this reference design + * file be used in conjunction or combination with any other product. + * + * alt_busy_sleep.c - Microsecond delay routine which uses a calibrated busy + * loop to perform the delay. This is used to implement + * usleep for both uC/OS-II and the standalone HAL. + * + * Author PRR + * + * Calibrated delay with no timer required + * + * The ASM instructions in the routine are equivalent to + * + * for (i=0;i +#include + +#include "system.h" +#include "alt_types.h" + +#include "priv/alt_busy_sleep.h" + +unsigned int alt_busy_sleep (unsigned int us) +{ +/* + * Only delay if ALT_SIM_OPTIMIZE is not defined; i.e., if software + * is built targetting ModelSim RTL simulation, the delay will be + * skipped to speed up simulation. + */ +#ifndef ALT_SIM_OPTIMIZE + int i; + int big_loops; + alt_u32 cycles_per_loop; + + if (!strcmp(NIOS2_CPU_IMPLEMENTATION,"tiny")) + { + cycles_per_loop = 9; + } + else + { + cycles_per_loop = 3; + } + + + big_loops = us / (INT_MAX/ + (ALT_CPU_FREQ/(cycles_per_loop * 1000000))); + + if (big_loops) + { + for(i=0;i + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +#ifdef ALT_USE_DIRECT_DRIVERS + +int ALT_CLOSE (int fildes) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(close); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +/* + * close() is called by an application to release a file descriptor. If the + * associated file system/device has a close() callback function registered + * then this called. The file descriptor is then marked as free. + * + * ALT_CLOSE is mapped onto the close() system call in alt_syscall.h + */ + +int ALT_CLOSE (int fildes) +{ + alt_fd* fd; + int rval; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (fildes < 0) ? NULL : &alt_fd_list[fildes]; + + if (fd) + { + /* + * If the associated file system/device has a close function, call it so + * that any necessary cleanup code can run. + */ + + rval = (fd->dev->close) ? fd->dev->close(fd) : 0; + + /* Free the file descriptor structure and return. */ + + alt_release_fd (fildes); + if (rval < 0) + { + ALT_ERRNO = -rval; + return -1; + } + return 0; + } + else + { + ALT_ERRNO = EBADFD; + return -1; + } +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_dcache_flush.c b/software/sys_controller_bsp/HAL/src/alt_dcache_flush.c new file mode 100644 index 0000000..5bdc043 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dcache_flush.c @@ -0,0 +1,70 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "nios2.h" +#include "system.h" + +#include "alt_types.h" +#include "sys/alt_cache.h" + +#define ALT_FLUSH_DATA(i) __asm__ volatile ("flushda (%0)" :: "r" (i)); + +/* + * alt_dcache_flush() is called to flush the data cache for a memory + * region of length "len" bytes, starting at address "start". + * + * Any dirty lines in the data cache are written back to memory. + */ + +void alt_dcache_flush (void* start, alt_u32 len) +{ +#if NIOS2_DCACHE_SIZE > 0 + + char* i; + char* end = ((char*) start) + len; + + for (i = start; i < end; i+= NIOS2_DCACHE_LINE_SIZE) + { + ALT_FLUSH_DATA(i); + } + + /* + * For an unaligned flush request, we've got one more line left. + * Note that this is dependent on NIOS2_DCACHE_LINE_SIZE to be a + * multiple of 2 (which it always is). + */ + + if (((alt_u32) start) & (NIOS2_DCACHE_LINE_SIZE - 1)) + { + ALT_FLUSH_DATA(i); + } + +#endif /* NIOS2_DCACHE_SIZE > 0 */ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_dcache_flush_all.c b/software/sys_controller_bsp/HAL/src/alt_dcache_flush_all.c new file mode 100644 index 0000000..6529231 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dcache_flush_all.c @@ -0,0 +1,51 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "nios2.h" +#include "system.h" + +#include "alt_types.h" +#include "sys/alt_cache.h" + +/* + * alt_dcache_flush_all() is called to flush the entire data cache. + */ + +void alt_dcache_flush_all (void) +{ +#if NIOS2_DCACHE_SIZE > 0 + char* i; + + for (i = (char*) 0; i < (char*) NIOS2_DCACHE_SIZE; i+= NIOS2_DCACHE_LINE_SIZE) + { + __asm__ volatile ("flushd (%0)" :: "r" (i)); + } +#endif /* NIOS2_DCACHE_SIZE > 0 */ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_dcache_flush_no_writeback.c b/software/sys_controller_bsp/HAL/src/alt_dcache_flush_no_writeback.c new file mode 100644 index 0000000..9da0ee8 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dcache_flush_no_writeback.c @@ -0,0 +1,69 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "nios2.h" +#include "system.h" + +#include "alt_types.h" +#include "sys/alt_cache.h" + +#define ALT_FLUSH_DATA_NO_WRITEBACK(i) \ + __asm__ volatile ("initda (%0)" :: "r" (i)); + +/* + * alt_dcache_flush_no_writeback() is called to flush the data cache for a + * memory region of length "len" bytes, starting at address "start". + * + * Any dirty lines in the data cache are NOT written back to memory. + * Make sure you really want this behavior. If you aren't 100% sure, + * use the alt_dcache_flush() routine instead. + */ + +void alt_dcache_flush_no_writeback (void* start, alt_u32 len) +{ + char* i; + char* end = ((char*) start) + len; + + for (i = start; i < end; i+= NIOS2_DCACHE_LINE_SIZE) + { + ALT_FLUSH_DATA_NO_WRITEBACK(i); + } + + /* + * For an unaligned flush request, we've got one more line left. + * Note that this is dependent on NIOS2_DCACHE_LINE_SIZE to be a + * multiple of 2 (which it always is). + */ + + if (((alt_u32) start) & (NIOS2_DCACHE_LINE_SIZE - 1)) + { + ALT_FLUSH_DATA_NO_WRITEBACK(i); + } +} diff --git a/software/sys_controller_bsp/HAL/src/alt_dev.c b/software/sys_controller_bsp/HAL/src/alt_dev.c new file mode 100644 index 0000000..ebc15e5 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dev.c @@ -0,0 +1,149 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + +#include "alt_types.h" + +#include "system.h" + +/* + * This file contains the data constructs used to control access to device and + * filesytems. + */ + +/* + * "alt_fs_list" is the head of a linked list of registered filesystems. It is + * initialised as an empty list. New entries can be added using the + * alt_fs_reg() function. + */ + +ALT_LLIST_HEAD(alt_fs_list); + + +/* + * "alt_dev_list" is the head of a linked list of registered devices. It is + * configured at startup to include a single device, "alt_dev_null". This + * device is discussed below. + */ + +extern alt_dev alt_dev_null; /* forward declaration */ + +alt_llist alt_dev_list = {&alt_dev_null.llist, &alt_dev_null.llist}; + +/* + * alt_dev_null_write() is the implementation of the write() function used + * by the alt_dev_null device. It simple discards all data passed to it, and + * indicates that the data has been successfully transmitted. + */ + +static int alt_dev_null_write (alt_fd* fd, const char* ptr, int len) +{ + return len; +} + +/* + * "alt_dev_null" is used to allow output to be redirected to nowhere. It is + * the only device registered before the call to alt_sys_init(). At startup + * stin, stdout & stderr are all directed towards this device so that library + * calls like printf() will be safe but inefectual. + */ + +alt_dev alt_dev_null = { + { + &alt_dev_list, + &alt_dev_list + }, + "/dev/null", + NULL, /* open */ + NULL, /* close */ + NULL, /* write */ + alt_dev_null_write, /* write */ + NULL, /* lseek */ + NULL, /* fstat */ + NULL /* ioctl */ + }; + +/* + * "alt_fd_list_lock" is a semaphore used to control access to the file + * descriptor list. This is used to ensure that access to the list is thread + * safe. + */ + +ALT_SEM(alt_fd_list_lock) + +/* + * "alt_max_fd" is used to make access to the file descriptor list more + * efficent. It is set to be the value of the highest allocated file + * descriptor. This saves having to search the entire pool of unallocated + * file descriptors when looking for a match. + */ + +alt_32 alt_max_fd = -1; + +/* + * "alt_fd_list" is the file descriptor pool. The first three entries in the + * array are configured as standard in, standard out, and standard error. These + * are all initialised so that accesses are directed to the alt_dev_null + * device. The remaining file descriptors are initialised as unallocated. + * + * The maximum number of file descriptors within the system is specified by the + * user defined macro "ALT_MAX_FD". This is defined in "system.h", which is + * auto-genereated using the projects PTF and STF files. + */ + +alt_fd alt_fd_list[ALT_MAX_FD] = + { + { + &alt_dev_null, /* standard in */ + 0, + 0 + }, + { + &alt_dev_null, /* standard out */ + 0, + 0 + }, + { + &alt_dev_null, /* standard error */ + 0, + 0 + } + /* all other elements are set to zero */ + }; diff --git a/software/sys_controller_bsp/HAL/src/alt_dev_llist_insert.c b/software/sys_controller_bsp/HAL/src/alt_dev_llist_insert.c new file mode 100644 index 0000000..fa7239d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dev_llist_insert.c @@ -0,0 +1,59 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "priv/alt_dev_llist.h" +#include "sys/alt_errno.h" + +/* + * + */ + +int alt_dev_llist_insert (alt_dev_llist* dev, alt_llist* list) +{ + /* + * check that the device exists, and that it has a valid name. + */ + + if (!dev || !dev->name) + { + ALT_ERRNO = EINVAL; + return -EINVAL; + } + + /* + * register the device. + */ + + alt_llist_insert(list, &dev->llist); + + return 0; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_dma_rxchan_open.c b/software/sys_controller_bsp/HAL/src/alt_dma_rxchan_open.c new file mode 100644 index 0000000..6ea3b78 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dma_rxchan_open.c @@ -0,0 +1,63 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_dma.h" +#include "sys/alt_errno.h" +#include "priv/alt_file.h" + +/* + * The list of registered DMA receive channels. + */ + +ALT_LLIST_HEAD(alt_dma_rxchan_list); + +/* + * alt_dma_txchan_open() is used to obtain an "alt_dma_txchan" descriptor for + * a DMA transmit device. The name is the name of the associated physical + * device (e.g. "/dev/dma_0"). + * + * The return value will be NULL on failure, and non-NULL otherwise. + */ + +alt_dma_rxchan alt_dma_rxchan_open (const char* name) +{ + alt_dma_rxchan dev; + + dev = (alt_dma_rxchan) alt_find_dev (name, &alt_dma_rxchan_list); + + if (!dev) + { + ALT_ERRNO = ENODEV; + } + + return dev; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_dma_txchan_open.c b/software/sys_controller_bsp/HAL/src/alt_dma_txchan_open.c new file mode 100644 index 0000000..f41fa81 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_dma_txchan_open.c @@ -0,0 +1,63 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_dma.h" +#include "sys/alt_errno.h" +#include "priv/alt_file.h" + +/* + * The list of registered receive channels. + */ + +ALT_LLIST_HEAD(alt_dma_txchan_list); + +/* + * alt_dma_txchan_open() is used to obtain an "alt_dma_txchan" descriptor for + * a DMA transmit device. The name is the name of the associated physical + * device (e.g. "/dev/dma_0"). + * + * The return value will be NULL on failure, and non-NULL otherwise. + */ + +alt_dma_txchan alt_dma_txchan_open (const char* name) +{ + alt_dma_txchan dev; + + dev = (alt_dma_txchan) alt_find_dev (name, &alt_dma_txchan_list); + + if (!dev) + { + ALT_ERRNO = ENODEV; + } + + return dev; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_do_ctors.c b/software/sys_controller_bsp/HAL/src/alt_do_ctors.c new file mode 100644 index 0000000..ff5a1f7 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_do_ctors.c @@ -0,0 +1,64 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT IT DIRECTLY. * +* * +* Overriding HAL Functions * +* * +* To provide your own implementation of a HAL function, include the file in * +* your Nios II IDE application project. When building the executable, the * +* Nios II IDE finds your function first, and uses it in place of the HAL * +* version. * +* * +******************************************************************************/ + +/* + * + */ + +typedef void (*constructor) (void); +extern constructor __CTOR_LIST__[]; +extern constructor __CTOR_END__[]; + +/* + * Run the C++ static constructors. + */ + +void _do_ctors(void) +{ + constructor* ctor; + + for (ctor = &__CTOR_END__[-1]; ctor >= __CTOR_LIST__; ctor--) + (*ctor) (); +} diff --git a/software/sys_controller_bsp/HAL/src/alt_do_dtors.c b/software/sys_controller_bsp/HAL/src/alt_do_dtors.c new file mode 100644 index 0000000..565c99f --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_do_dtors.c @@ -0,0 +1,64 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* THIS IS A LIBRARY READ-ONLY SOURCE FILE. DO NOT EDIT IT DIRECTLY. * +* * +* Overriding HAL Functions * +* * +* To provide your own implementation of a HAL function, include the file in * +* your Nios II IDE application project. When building the executable, the * +* Nios II IDE finds your function first, and uses it in place of the HAL * +* version. * +* * +******************************************************************************/ + +/* + * + */ + +typedef void (*destructor) (void); +extern destructor __DTOR_LIST__[]; +extern destructor __DTOR_END__[]; + +/* + * Run the C++ static destructors. + */ + +void _do_dtors(void) +{ + destructor* dtor; + + for (dtor = &__DTOR_END__[-1]; dtor >= __DTOR_LIST__; dtor--) + (*dtor) (); +} diff --git a/software/sys_controller_bsp/HAL/src/alt_ecc_fatal_entry.S b/software/sys_controller_bsp/HAL/src/alt_ecc_fatal_entry.S new file mode 100644 index 0000000..9b43c01 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_ecc_fatal_entry.S @@ -0,0 +1,102 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2013 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* + * This is the code called at the beginning of the exception handler + * to detect a likely fatal ECC error exception and then jump to + * user-provided code to handle it. + * + * This code is pulled in from a .globl in alt_ecc_fatal_exception.c. + * This scheme is used so that if a handler is never registered, then this + * code will not appear in the generated executable, thereby improving + * code footprint. + * + * This code is located in its own section that the linker script + * explicitly mentions and ensures it gets linked at the beginning + * of the exception handler. + */ + + /* + * Pull in the exception handler register save code. + */ + .globl alt_exception + + .section .exceptions.entry.ecc_fatal, "xa" + + /* + * This might be handling an unrecoverable ECC error exception + * in the register file and/or data cache. + * Must avoid reading registers or performing load/store instructions + * before this is determined because they could trigger another + * unrecoverable ECC error exception and create an infinite loop. + * + * The EXCEPTION register is always present when ECC is present. + * Bit 31 of this register indicates that there was an unrecoverable + * ECC error exception in the register file and/or data cache. + * Test this (using blt to check sign bit) to determine if this is + * what we are dealing with. Otherwise, just do normal processing. + * + * Jump to an application-provided routine to handle this condition. + * Pass in the return address in the et register in case this code + * can clean up the ECC error and then return here (unlikely). + * + * Runtime stack checking can't be enabled when ECC is present + * because they both want to use the et register. + */ + rdctl et, exception + bge et, r0, alt_exception_not_ecc_fatal /* Not ECCFTL if bit 31 is 0 */ + + /* + * Load ECC fatal handler pointer into et register. + * Using a ldwio is safe because it completely bypasses the data cache. + */ + movhi et, %hi(alt_exception_ecc_fatal_handler) + ori et, et, %lo(alt_exception_ecc_fatal_handler) + ldwio et, 0(et) + + /* + * If ECC fatal handler pointer is not 0, assume a handler + * has been provided by the application. + */ + beq et, r0, alt_exception_not_ecc_fatal + + /* + * The et register contains the address of the ECC fatal handler. + * Jump to this address to invoke the handler. + */ + jmp et + + /* + * An ECC fatal handler can jump to this label if it able + * to recover from the fatal error (rare) and wants to continue + * with normal exception processing. + */ +.globl alt_exception_not_ecc_fatal +alt_exception_not_ecc_fatal: diff --git a/software/sys_controller_bsp/HAL/src/alt_ecc_fatal_exception.c b/software/sys_controller_bsp/HAL/src/alt_ecc_fatal_exception.c new file mode 100644 index 0000000..2b8d0e9 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_ecc_fatal_exception.c @@ -0,0 +1,75 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2013 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ +#include "io.h" +#include "sys/alt_exceptions.h" +#include "sys/alt_cache.h" + +/* + * This file implements support for calling a user-registered handler + * when a likely fatal ECC error exception occurs. + */ + +/* + * Global variable containing address to jump to when likely fatal + * ECC error exception occurs. + */ +alt_u32 alt_exception_ecc_fatal_handler = 0x0; + +/* + * Pull in the exception entry assembly code. This will not be linked in + * unless this object is linked into the executable (i.e. only if + * alt_ecc_fatal_exception_register() is called). + */ +__asm__( "\n\t.globl alt_exception" ); + +/* + * alt_ecc_fatal_exception_register() is called to register a handler to + * service likely fatal ECC error exceptions. + * + * Passing null (0x0) in the handler argument will disable a previously- + * registered handler. + * + * Note that if no handler is registered, just normal exception processing + * occurs on a likely fatal ECC exception and the exception processing + * code might trigger an infinite exception loop. + */ +void +alt_ecc_fatal_exception_register(alt_u32 handler) +{ + alt_exception_ecc_fatal_handler = handler; + + /* + * Flush this from the cache. Required because the exception handler uses ldwio + * to read this value to avoid trigger another data cache ECC error exception. + */ + alt_dcache_flush(&alt_exception_ecc_fatal_handler, sizeof(alt_exception_ecc_fatal_handler)); +} diff --git a/software/sys_controller_bsp/HAL/src/alt_env_lock.c b/software/sys_controller_bsp/HAL/src/alt_env_lock.c new file mode 100644 index 0000000..fc25a0c --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_env_lock.c @@ -0,0 +1,53 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +/* + * These are the empty env lock/unlock stubs required by newlib. These are + * used to make accesses to environment variables thread safe. The default HAL + * configuration is single threaded, so there is nothing to do here. Note that + * this requires that environment variables are never manipulated by an interrupt + * service routine. + */ + +void __env_lock ( struct _reent *_r ) +{ +} + +/* + * + */ + +void __env_unlock ( struct _reent *_r ) +{ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_environ.c b/software/sys_controller_bsp/HAL/src/alt_environ.c new file mode 100644 index 0000000..404efc4 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_environ.c @@ -0,0 +1,42 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "os/alt_syscall.h" + +/* + * These are the environment variables passed to the C code. By default there + * are no variables registered. An application can manipulate this list using + * getenv() and setenv(). + */ + +char *__env[1] = { 0 }; +char **ALT_ENVIRON = __env; diff --git a/software/sys_controller_bsp/HAL/src/alt_errno.c b/software/sys_controller_bsp/HAL/src/alt_errno.c new file mode 100644 index 0000000..1d8368d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_errno.c @@ -0,0 +1,44 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/* + * This file defines the alt_errno global variable. See comments in + * alt_errno.h for the use of this variable. + */ + + +#include "sys/alt_errno.h" +#include "alt_types.h" + +extern int ALT_WEAK *__errno (void); + +int* (*alt_errno) (void) = __errno; diff --git a/software/sys_controller_bsp/HAL/src/alt_exception_entry.S b/software/sys_controller_bsp/HAL/src/alt_exception_entry.S new file mode 100644 index 0000000..dd7b418 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_exception_entry.S @@ -0,0 +1,376 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "system.h" + +/* + * This is the exception entry point code, which saves all the caller saved + * registers and then handles the appropriate exception. It should be pulled + * in using a .globl from all the exception handler routines. This scheme is + * used so that if an interrupt is never registered, then this code will not + * appear in the generated executable, thereby improving code footprint. + * + * If an external interrpt controller (EIC) is present, it will supply an + * interrupt vector address to the processor when an interrupt occurs. For + * The Altera Vectored Interrupt Controller (VIC) driver will establish a + * vector table and the processor will jump directly to the appropriate + * table entry, funnel routine, and then user ISR. This will bypass this code + * in entirety. This code might still be linked into a system with an EIC, + * but would then be used only for non-interrupt exceptions. + */ + + /* + * Explicitly allow the use of r1 (the assembler temporary register) + * within this code. This register is normally reserved for the use of + * the assembler. + */ + .set noat + + /* + * The top and bottom of the exception stack. + */ +#ifdef ALT_EXCEPTION_STACK + .globl __alt_exception_stack_pointer + +#ifdef ALT_STACK_CHECK + .globl __alt_exception_stack_limit + + /* + * Store the value of the stack limit after interrupt somewhere. + */ + .globl alt_exception_old_stack_limit +#endif /* ALT_STACK_CHECK */ +#endif /* ALT_EXCEPTION_STACK */ + +/* + * The code at alt_exception is located at the Nios II exception + * handler address. + */ + .section .exceptions.entry.label, "xa" + .globl alt_exception + .type alt_exception, @function +alt_exception: + + /* + * The code for detecting a likely fatal ECC exception is + * linked here before the normal exception handler code if required. + * This is handled by the linker script and putting that code + * in the .exceptions.entry.ecc_fatal section. + */ + + /* + * Now start the normal exception handler code. + */ + .section .exceptions.entry, "xa" + +#ifdef ALT_EXCEPTION_STACK +#ifdef ALT_STACK_CHECK + /* + * When runtime stack checking is enabled, the et register + * contains the stack limit. Save this in memory before + * overwriting the et register. + */ + stw et, %gprel(alt_exception_old_stack_limit)(gp) +#endif /* ALT_STACK_CHECK */ + + /* + * Switch to the exception stack and save the current stack pointer + * in memory. Uses the et register as a scratch register. + */ + movhi et, %hi(__alt_exception_stack_pointer - 80) + ori et, et, %lo(__alt_exception_stack_pointer - 80) + stw sp, 76(et) + mov sp, et + +#ifdef ALT_STACK_CHECK + /* + * Restore the stack limit from memory to the et register. + */ + movhi et, %hi(__alt_exception_stack_limit) + ori et, et, %lo(__alt_exception_stack_limit) + stw et, %gprel(alt_stack_limit_value)(gp) +#endif /* ALT_STACK_CHECK */ + +#else /* ALT_EXCEPTION_STACK disabled */ + /* + * Reserve space on normal stack for registers about to be pushed. + */ + addi sp, sp, -76 + +#ifdef ALT_STACK_CHECK + /* Ensure stack didn't just overflow. */ + bltu sp, et, .Lstack_overflow +#endif /* ALT_STACK_CHECK */ + +#endif /* ALT_EXCEPTION_STACK */ + + /* + * Process an exception. For all exceptions we must preserve all + * caller saved registers on the stack (See the Nios II ABI + * documentation for details). + * + * Leave a gap in the stack frame at 4(sp) for the muldiv handler to + * store zero into. + */ + stw ra, 0(sp) + stw r1, 8(sp) + stw r2, 12(sp) + stw r3, 16(sp) + stw r4, 20(sp) + stw r5, 24(sp) + stw r6, 28(sp) + stw r7, 32(sp) + rdctl r5, estatus /* Read early to avoid usage stall */ + stw r8, 36(sp) + stw r9, 40(sp) + stw r10, 44(sp) + stw r11, 48(sp) + stw r12, 52(sp) + stw r13, 56(sp) + stw r14, 60(sp) + stw r15, 64(sp) + + /* + * ea-4 contains the address of the instruction being executed + * when the exception occured. For interrupt exceptions, we will + * will be re-issue the isntruction. Store it in 72(sp) + */ + stw r5, 68(sp) /* estatus */ + addi r15, ea, -4 /* instruction that caused exception */ + stw r15, 72(sp) + + /* + * The interrupt testing code (.exceptions.irqtest) will be + * linked here. If the Internal Interrupt Controller (IIC) is + * present (an EIC is not present), the presense of an interrupt + * is determined by examining CPU control registers or an interrupt + * custom instruction, if present. + * + * If the IIC is used and an interrupt is active, the code linked + * here will call the HAL IRQ handler (alt_irq_handler()) which + * successively calls registered interrupt handler(s) until no + * interrupts remain pending. It then jumps to .exceptions.exit. If + * there is no interrupt then it continues to .exception.notirq, below. + */ + + .section .exceptions.notirq, "xa" + + /* + * Prepare to service unimplemtned instructions or traps, + * each of which is optionally inked into section .exceptions.soft, + * which will preceed .exceptions.unknown below. + * + * Unlike interrupts, we want to skip the exception-causing instructon + * upon completion, so we write ea (address of instruction *after* + * the one where the exception occured) into 72(sp). The actual + * instruction that caused the exception is written in r2, which these + * handlers will utilize. + */ + stw ea, 72(sp) /* Don't re-issue */ + +#ifdef NIOS2_CDX_PRESENT + mov.n r4, ea + subi.n r4, r4, 4 + ldhu.n r2, 0(r4) + ldhu.n r3, 2(r4) + slli.n r3, r3, 16 + or.n r2, r2, r3 /* Instruction that caused exception */ +#else + ldw r2, -4(ea) /* Instruction that caused exception */ +#endif + /* + * Other exception handling code, if enabled, will be linked here. + * This includes unimplemted (multiply/divide) instruction support + * (a BSP generaton option), and a trap handler (that would typically + * be augmented with user-specific code). These are not linked in by + * default. + */ + + /* + * In the context of linker sections, "unknown" are all exceptions + * not handled by the built-in handlers above (interupt, and trap or + * unimplemented instruction decoding, if enabled). + * + * Advanced exception types can be serviced by registering a handler. + * To do so, enable the "Enable Instruction-related Exception API" HAL + * BSP setting. If this setting is disabled, this handler code will + * either break (if the debug core is present) or enter an infinite + * loop because we don't how how to handle the exception. + */ + .section .exceptions.unknown +#ifdef ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API + /* + * The C-based HAL routine alt_instruction_exception_entry() will + * attempt to service the exception by calling a user-registered + * exception handler using alt_instruction_exception_register(). + * If no handler was registered it will either break (if the + * debugger is present) or go into an infinite loop since the + * handling behavior is undefined; in that case we will not return here. + */ + + /* Load exception-causing address as first argument (r4) */ + addi r4, ea, -4 + + /* Call the instruction-exception entry */ + call alt_instruction_exception_entry + + /* + * If alt_instruction_exception_entry() returned, the exception was + * serviced by a user-registered routine. Its return code (now in r2) + * indicates whether to re-issue or skip the exception-causing + * instruction + * + * Return code was 0: Skip. The instruction after the exception is + * already stored in 72(sp). + */ + bne r2, r0, .Lexception_exit + + /* + * Otherwise, modify 72(sp) to re-issue the instruction that caused the + * exception. + */ + addi r15, ea, -4 /* instruction that caused exception */ + stw r15, 72(sp) + +#else /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API disabled */ + + /* + * We got here because an instruction-related exception occured, but the + * handler API was not compiled in. We do not presume to know how to + * handle it. If the debugger is present, break, otherwise hang. + * + * If you get here then one of the following could have happened: + * + * - An instruction-generated exception occured, and the processor + * does not have the extra exceptions feature enabled, or you + * have not registered a handler using + * alt_instruction_exception_register() + * + * Some examples of instruction-generated exceptions and why they + * might occur: + * + * - Your program could have been compiled for a full-featured + * Nios II core, but it is running on a smaller core, and + * instruction emulation has been disabled by defining + * ALT_NO_INSTRUCTION_EMULATION. + * + * You can work around the problem by re-enabling instruction + * emulation, or you can figure out why your program is being + * compiled for a system other than the one that it is running on. + * + * - Your program has executed a trap instruction, but has not + * implemented a handler for this instruction. + * + * - Your program has executed an illegal instruction (one which is + * not defined in the instruction set). + * + * - Your processor includes an MMU or MPU, and you have enabled it + * before registering an exception handler to service exceptions it + * generates. + * + * The problem could also be hardware related: + * - If your hardware is broken and is generating spurious interrupts + * (a peripheral which negates its interrupt output before its + * interrupt handler has been executed will cause spurious + * interrupts) + */ +alt_exception_unknown: +#ifdef NIOS2_HAS_DEBUG_STUB + /* + * Either tell the user now (if there is a debugger attached) or go into + * the debug monitor which will loop until a debugger is attached. + */ + break +#else /* NIOS2_HAS_DEBUG_STUB disabled */ + /* + * If there is no debug stub, an infinite loop is more useful. + */ + br alt_exception_unknown +#endif /* NIOS2_HAS_DEBUG_STUB */ +#endif /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API */ + + .section .exceptions.exit.label +.Lexception_exit: + + .section .exceptions.exit, "xa" + + /* + * Restore the saved registers, so that all general purpose registers + * have been restored to their state at the time the interrupt occured. + */ + + ldw r5, 68(sp) + ldw ea, 72(sp) /* This becomes the PC once eret is executed */ + ldw ra, 0(sp) + + wrctl estatus, r5 + + ldw r1, 8(sp) + ldw r2, 12(sp) + ldw r3, 16(sp) + ldw r4, 20(sp) + ldw r5, 24(sp) + ldw r6, 28(sp) + ldw r7, 32(sp) + +#if defined(ALT_EXCEPTION_STACK) && defined(ALT_STACK_CHECK) + ldw et, %gprel(alt_exception_old_stack_limit)(gp) +#endif + + ldw r8, 36(sp) + ldw r9, 40(sp) + ldw r10, 44(sp) + ldw r11, 48(sp) + ldw r12, 52(sp) + ldw r13, 56(sp) + ldw r14, 60(sp) + ldw r15, 64(sp) + +#ifdef ALT_EXCEPTION_STACK +#ifdef ALT_STACK_CHECK + stw et, %gprel(alt_stack_limit_value)(gp) + stw zero, %gprel(alt_exception_old_stack_limit)(gp) +#endif /* ALT_STACK_CHECK */ + ldw sp, 76(sp) +#else /* ALT_EXCEPTION_STACK disabled */ + addi sp, sp, 76 +#endif /* ALT_EXCEPTION_STACK */ + + /* + * Return to the interrupted instruction. + */ + + eret + +#ifdef ALT_STACK_CHECK +.Lstack_overflow: + break 3 +#endif /* ALT_STACK_CHECK */ + diff --git a/software/sys_controller_bsp/HAL/src/alt_exception_muldiv.S b/software/sys_controller_bsp/HAL/src/alt_exception_muldiv.S new file mode 100644 index 0000000..55617a6 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_exception_muldiv.S @@ -0,0 +1,583 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + + /* + * This is the software multiply/divide handler for Nios2. + */ + + /* + * Provide a label which can be used to pull this file in. + */ + + .section .exceptions.start + .globl alt_exception_muldiv +alt_exception_muldiv: + + /* + * Pull in the entry/exit code. + */ + .globl alt_exception + + + .section .exceptions.soft, "xa" + + + /* INSTRUCTION EMULATION + * --------------------- + * + * Nios II processors generate exceptions for unimplemented instructions. + * The routines below emulate these instructions. Depending on the + * processor core, the only instructions that might need to be emulated + * are div, divu, mul, muli, mulxss, mulxsu, and mulxuu. + * + * The emulations match the instructions, except for the following + * limitations: + * + * 1) The emulation routines do not emulate the use of the exception + * temporary register (et) as a source operand because the exception + * handler already has modified it. + * + * 2) The routines do not emulate the use of the stack pointer (sp) or the + * exception return address register (ea) as a destination because + * modifying these registers crashes the exception handler or the + * interrupted routine. + * + * 3) To save code size, the routines do not emulate the use of the + * breakpoint registers (ba and bt) as operands. + * + * Detailed Design + * --------------- + * + * The emulation routines expect the contents of integer registers r0-r31 + * to be on the stack at addresses sp, 4(sp), 8(sp), ... 124(sp). The + * routines retrieve source operands from the stack and modify the + * destination register's value on the stack prior to the end of the + * exception handler. Then all registers except the destination register + * are restored to their previous values. + * + * The instruction that causes the exception is found at address -4(ea). + * The instruction's OP and OPX fields identify the operation to be + * performed. + * + * One instruction, muli, is an I-type instruction that is identified by + * an OP field of 0x24. + * + * muli AAAAA,BBBBB,IIIIIIIIIIIIIIII,-0x24- + * 27 22 6 0 <-- LSB of field + * + * The remaining emulated instructions are R-type and have an OP field + * of 0x3a. Their OPX fields identify them. + * + * R-type AAAAA,BBBBB,CCCCC,XXXXXX,NNNNN,-0x3a- + * 27 22 17 11 6 0 <-- LSB of field + * + * + */ + + + /* + * Split the instruction into its fields. We need 4*A, 4*B, and 4*C as + * offsets to the stack pointer for access to the stored register values. + */ + /* r2 = AAAAA,BBBBB,IIIIIIIIIIIIIIII,PPPPPP */ + roli r3, r2, 7 /* r3 = BBB,IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BB */ + roli r4, r3, 3 /* r4 = IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB */ + roli r6, r4, 2 /* r6 = IIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB,II */ + srai r4, r4, 16 /* r4 = (sign-extended) IMM16 */ + xori r6, r6, 0x42 /* r6 = CCC,XXXXXX,NNNNN,PPPPPP,AAAAA,bBBBB,cC */ + roli r7, r6, 5 /* r7 = XXXX,NNNNN,PPPPPP,AAAAA,bBBBB,cCCCC,XX */ + andi r5, r2, 0x3f /* r5 = 00000000000000000000000000,PPPPPP */ + xori r3, r3, 0x40 + andi r3, r3, 0x7c /* r3 = 0000000000000000000000000,aAAAA,00 */ + andi r6, r6, 0x7c /* r6 = 0000000000000000000000000,bBBBB,00 */ + andi r7, r7, 0x7c /* r7 = 0000000000000000000000000,cCCCC,00 */ + + /* Now either + * r5 = OP + * r3 = 4*(A^16) + * r4 = IMM16 (sign extended) + * r6 = 4*(B^16) + * r7 = 4*(C^16) + * or + * r5 = OP + */ + + + /* + * Save everything on the stack to make it easy for the emulation routines + * to retrieve the source register operands. The exception entry code has + * already saved some of this so we don't need to do it all again. + */ + + addi sp, sp, -60 + stw zero, 64(sp) /* Save zero on stack to avoid special case for r0. */ + /* Register at and r2-r15 have already been saved. */ + + stw r16, 0(sp) + stw r17, 4(sp) + stw r18, 8(sp) + stw r19, 12(sp) + stw r20, 16(sp) + stw r21, 20(sp) + stw r22, 24(sp) + stw r23, 28(sp) + /* et @ 32 - Has already been changed.*/ + /* bt @ 36 - Usually isn't an operand. */ + stw gp, 40(sp) + stw sp, 44(sp) + stw fp, 48(sp) + /* ea @ 52 - Don't bother to save - it's already been changed */ + /* ba @ 56 - Breakpoint register usually isn't an operand */ + /* ra @ 60 - Has already been saved */ + + + /* + * Prepare for either multiplication or division loop. + * They both loop 32 times. + */ + movi r14, 32 + + + /* + * Get the operands. + * + * It is necessary to check for muli because it uses an I-type instruction + * format, while the other instructions are have an R-type format. + */ + add r3, r3, sp /* r3 = address of A-operand. */ + ldw r3, 0(r3) /* r3 = A-operand. */ + movi r15, 0x24 /* muli opcode (I-type instruction format) */ + beq r5, r15, .Lmul_immed /* muli doesn't use the B register as a source */ + + add r6, r6, sp /* r6 = address of B-operand. */ + ldw r6, 0(r6) /* r6 = B-operand. */ + /* r4 = SSSSSSSSSSSSSSSS,-----IMM16------ */ + /* IMM16 not needed, align OPX portion */ + /* r4 = SSSSSSSSSSSSSSSS,CCCCC,-OPX--,00000 */ + srli r4, r4, 5 /* r4 = 00000,SSSSSSSSSSSSSSSS,CCCCC,-OPX-- */ + andi r4, r4, 0x3f /* r4 = 00000000000000000000000000,-OPX-- */ + + /* Now + * r5 = OP + * r3 = src1 + * r6 = src2 + * r4 = OPX (no longer can be muli) + * r7 = 4*(C^16) + * r14 = loop counter + */ + + /* ILLEGAL-INSTRUCTION EXCEPTION + * ----------------------------- + * + * This code is for Nios II cores that generate exceptions when attempting + * to execute illegal instructions. Nios II cores that support an + * illegal-instruction exception are identified by the presence of the + * macro definition NIOS2_HAS_ILLEGAL_INSTRUCTION_EXCEPTION in system.h . + * + * Remember that illegal instructions are different than unimplemented + * instructions. Illegal instructions are instruction encodings that + * have not been defined by the Nios II ISA. Unimplemented instructions + * are legal instructions that must be emulated by some Nios II cores. + * + * If we get here, all instructions except multiplies and divides + * are illegal. + * + * This code assumes that OP is not muli (because muli was tested above). + * All other multiplies and divides are legal. Anything else is illegal. + */ + + movi r8, 0x3a /* OP for R-type mul* and div* */ + bne r5, r8, .Lnot_muldiv + + /* r15 already is 0x24 */ /* OPX of divu */ + beq r4, r15, .Ldivide + + movi r15,0x27 /* OPX of mul */ + beq r4, r15, .Lmultiply + + movi r15,0x07 /* OPX of mulxuu */ + beq r4, r15, .Lmultiply + + movi r15,0x17 /* OPX of mulxsu */ + beq r4, r15, .Lmultiply + + movi r15,0x1f /* OPX of mulxss */ + beq r4, r15, .Lmultiply + + movi r15,0x25 /* OPX of div */ + bne r4, r15, .Lnot_muldiv + + + /* DIVISION + * + * Divide an unsigned dividend by an unsigned divisor using + * a shift-and-subtract algorithm. The example below shows + * 43 div 7 = 6 for 8-bit integers. This classic algorithm uses a + * single register to store both the dividend and the quotient, + * allowing both values to be shifted with a single instruction. + * + * remainder dividend:quotient + * --------- ----------------- + * initialize 00000000 00101011: + * shift 00000000 0101011:_ + * remainder >= divisor? no 00000000 0101011:0 + * shift 00000000 101011:0_ + * remainder >= divisor? no 00000000 101011:00 + * shift 00000001 01011:00_ + * remainder >= divisor? no 00000001 01011:000 + * shift 00000010 1011:000_ + * remainder >= divisor? no 00000010 1011:0000 + * shift 00000101 011:0000_ + * remainder >= divisor? no 00000101 011:00000 + * shift 00001010 11:00000_ + * remainder >= divisor? yes 00001010 11:000001 + * remainder -= divisor - 00000111 + * ---------- + * 00000011 11:000001 + * shift 00000111 1:000001_ + * remainder >= divisor? yes 00000111 1:0000011 + * remainder -= divisor - 00000111 + * ---------- + * 00000000 1:0000011 + * shift 00000001 :0000011_ + * remainder >= divisor? no 00000001 :00000110 + * + * The quotient is 00000110. + */ + +.Ldivide: + /* + * Prepare for division by assuming the result + * is unsigned, and storing its "sign" as 0. + */ + movi r17, 0 + + + /* Which division opcode? */ + xori r15, r4, 0x25 /* OPX of div */ + bne r15, zero, .Lunsigned_division + + + /* + * OPX is div. Determine and store the sign of the quotient. + * Then take the absolute value of both operands. + */ + xor r17, r3, r6 /* MSB contains sign of quotient */ + bge r3, zero, 0f + sub r3, zero, r3 /* -r3 */ +0: + bge r6, zero, 0f + sub r6, zero, r6 /* -r6 */ +0: + + +.Lunsigned_division: + /* Initialize the unsigned-division loop. */ + movi r13, 0 /* remainder = 0 */ + + /* Now + * r3 = dividend : quotient + * r4 = 0x25 for div, 0x24 for divu + * r6 = divisor + * r13 = remainder + * r14 = loop counter (already initialized to 32) + * r17 = MSB contains sign of quotient + */ + + + /* + * for (count = 32; count > 0; --count) + * { + */ +.Ldivide_loop: + + /* + * Division: + * + * (remainder:dividend:quotient) <<= 1; + */ + slli r13, r13, 1 + cmplt r15, r3, zero /* r15 = MSB of r3 */ + or r13, r13, r15 + slli r3, r3, 1 + + + /* + * if (remainder >= divisor) + * { + * set LSB of quotient + * remainder -= divisor; + * } + */ + bltu r13, r6, .Ldiv_skip + ori r3, r3, 1 + sub r13, r13, r6 +.Ldiv_skip: + + /* + * } + */ + subi r14, r14, 1 + bne r14, zero, .Ldivide_loop + + mov r9, r3 + + + /* Now + * r9 = quotient + * r4 = 0x25 for div, 0x24 for divu + * r7 = 4*(C^16) + * r17 = MSB contains sign of quotient + */ + + + /* + * Conditionally negate signed quotient. If quotient is unsigned, + * the sign already is initialized to 0. + */ + bge r17, zero, .Lstore_result + sub r9, zero, r9 /* -r9 */ + + br .Lstore_result + + + + + /* MULTIPLICATION + * + * A "product" is the number that one gets by summing a "multiplicand" + * several times. The "multiplier" specifies the number of copies of the + * multiplicand that are summed. + * + * Actual multiplication algorithms don't use repeated addition, however. + * Shift-and-add algorithms get the same answer as repeated addition, and + * they are faster. To compute the lower half of a product (pppp below) + * one shifts the product left before adding in each of the partial products + * (a * mmmm) through (d * mmmm). + * + * To compute the upper half of a product (PPPP below), one adds in the + * partial products (d * mmmm) through (a * mmmm), each time following the + * add by a right shift of the product. + * + * mmmm + * * abcd + * ------ + * #### = d * mmmm + * #### = c * mmmm + * #### = b * mmmm + * #### = a * mmmm + * -------- + * PPPPpppp + * + * The example above shows 4 partial products. Computing actual Nios II + * products requires 32 partials. + * + * It is possible to compute the result of mulxsu from the result of mulxuu + * because the only difference between the results of these two opcodes is + * the value of the partial product associated with the sign bit of rA. + * + * mulxsu = mulxuu - ((rA < 0) ? rB : 0); + * + * It is possible to compute the result of mulxss from the result of mulxsu + * because the only difference between the results of these two opcodes is + * the value of the partial product associated with the sign bit of rB. + * + * mulxss = mulxsu - ((rB < 0) ? rA : 0); + * + */ + +.Lmul_immed: + /* Opcode is muli. Change it into mul for remainder of algorithm. */ + mov r7, r6 /* Field B is dest register, not field C. */ + mov r6, r4 /* Field IMM16 is src2, not field B. */ + movi r4, 0x27 /* OPX of mul is 0x27 */ + +.Lmultiply: + /* Initialize the multiplication loop. */ + movi r9, 0 /* mul_product = 0 */ + movi r10, 0 /* mulxuu_product = 0 */ + mov r11, r6 /* save original multiplier for mulxsu and mulxss */ + mov r12, r6 /* mulxuu_multiplier (will be shifted) */ + movi r16, 1 /* used to create "rori B,A,1" from "ror B,A,r16" */ + + /* Now + * r3 = multiplicand + * r6 = mul_multiplier + * r7 = 4 * dest_register (used later as offset to sp) + * r9 = mul_product + * r10 = mulxuu_product + * r11 = original multiplier + * r12 = mulxuu_multiplier + * r14 = loop counter (already initialized) + * r15 = temp + * r16 = 1 + */ + + + /* + * for (count = 32; count > 0; --count) + * { + */ +.Lmultiply_loop: + + /* + * mul_product <<= 1; + * lsb = multiplier & 1; + */ + slli r9, r9, 1 + andi r15, r12, 1 + + /* + * if (lsb == 1) + * { + * mulxuu_product += multiplicand; + * } + */ + beq r15, zero, .Lmulx_skip + add r10, r10, r3 + cmpltu r15, r10, r3 /* Save the carry from the MSB of mulxuu_product. */ + ror r15, r15, r16 /* r15 = 0x80000000 on carry, or else 0x00000000 */ +.Lmulx_skip: + + /* + * if (MSB of mul_multiplier == 1) + * { + * mul_product += multiplicand; + * } + */ + bge r6, zero, .Lmul_skip + add r9, r9, r3 +.Lmul_skip: + + /* + * mulxuu_product >>= 1; logical shift + * mul_multiplier <<= 1; done with MSB + * mulx_multiplier >>= 1; done with LSB + */ + srli r10, r10, 1 + or r10, r10, r15 /* OR in the saved carry bit. */ + slli r6, r6, 1 + srli r12, r12, 1 + + + /* + * } + */ + subi r14, r14, 1 + bne r14, zero, .Lmultiply_loop + + + /* + * Multiply emulation loop done. + */ + + /* Now + * r3 = multiplicand + * r4 = OPX + * r7 = 4 * dest_register (used later as offset to sp) + * r9 = mul_product + * r10 = mulxuu_product + * r11 = original multiplier + * r15 = temp + */ + + + /* + * Select/compute the result based on OPX. + */ + + + /* OPX == mul? Then store. */ + xori r15, r4, 0x27 + beq r15, zero, .Lstore_result + + /* It's one of the mulx.. opcodes. Move over the result. */ + mov r9, r10 + + /* OPX == mulxuu? Then store. */ + xori r15, r4, 0x07 + beq r15, zero, .Lstore_result + + /* Compute mulxsu + * + * mulxsu = mulxuu - ((rA < 0) ? rB : 0); + */ + bge r3, zero, .Lmulxsu_skip + sub r9, r9, r11 +.Lmulxsu_skip: + + /* OPX == mulxsu? Then store. */ + xori r15, r4, 0x17 + beq r15, zero, .Lstore_result + + /* Compute mulxss + * + * mulxss = mulxsu - ((rB < 0) ? rA : 0); + */ + bge r11, zero, .Lmulxss_skip + sub r9, r9, r3 +.Lmulxss_skip: + /* At this point, assume that OPX is mulxss, so store */ + + +.Lstore_result: + add r7, r7, sp + stw r9, 0(r7) + + ldw r16, 0(sp) + ldw r17, 4(sp) + ldw r18, 8(sp) + ldw r19, 12(sp) + ldw r20, 16(sp) + ldw r21, 20(sp) + ldw r22, 24(sp) + ldw r23, 28(sp) + + /* bt @ 32 - Breakpoint register usually isn't an operand. */ + /* et @ 36 - Don't corrupt et. */ + /* gp @ 40 - Don't corrupt gp. */ + /* sp @ 44 - Don't corrupt sp. */ + ldw fp, 48(sp) + /* ea @ 52 - Don't corrupt ea. */ + /* ba @ 56 - Breakpoint register usually isn't an operand. */ + + addi sp, sp, 60 + + br .Lexception_exit + + +.Lnot_muldiv: + + addi sp, sp, 60 + + + .section .exceptions.exit.label +.Lexception_exit: + diff --git a/software/sys_controller_bsp/HAL/src/alt_exception_trap.S b/software/sys_controller_bsp/HAL/src/alt_exception_trap.S new file mode 100644 index 0000000..b1bb6c2 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_exception_trap.S @@ -0,0 +1,95 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + + /* + * This is the trap exception handler for Nios2. + */ + + /* + * Provide a label which can be used to pull this file in. + */ + + .section .exceptions.start + .globl alt_exception_trap +alt_exception_trap: + + /* + * Pull in the entry/exit code. + */ + .globl alt_exception + + .section .exceptions.soft, "xa" + +.Ltrap_handler: + + /* + * Did a trap instruction cause the exception? + * + * The instruction which the exception occurred on has been loaded + * into r2 by code in alt_exception_entry.S + * + */ + +#ifdef ALT_CPU_CPU_ARCH_NIOS2_R2 + movhi r3,0xb41d /* upper half of trap opcode */ + ori r3,r3,0x0020 /* lower half of trap opcode */ + beq r2,r3,.Lis_trap +#ifdef NIOS2_CDX_PRESENT + mov r3,r2 + andhi r3,r3,0xffff + ori r3,r3,0xd009 /* trap.n opcode */ + beq r2,r3,.Lis_trap +#endif + br .Lnot_trap +#else + movhi r3,0x003b /* upper half of trap opcode */ + ori r3,r3,0x683a /* lower half of trap opcode */ + bne r2,r3,.Lnot_trap +#endif + +.Lis_trap: + /* + * There is no trap handler defined here, and so executing a trap + * instruction causes a software break. If you provide a trap handler, + * then you must replace the break instruction below with your handler. + * Your handler must preserve ea and the usual callee saved registers. + */ + + break + + br .Lexception_exit + +.Lnot_trap: + + + .section .exceptions.exit.label +.Lexception_exit: + + diff --git a/software/sys_controller_bsp/HAL/src/alt_execve.c b/software/sys_controller_bsp/HAL/src/alt_execve.c new file mode 100644 index 0000000..27b99cf --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_execve.c @@ -0,0 +1,55 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "os/alt_syscall.h" + +/* + * execve() is used by newlib to launch new processes. This is unsupported in + * the HAL environment. However a "do-nothing" implementation is still + * provied for newlib compatability. + * + * ALT_EXECVE is mapped onto the execve() system call in alt_syscall.h + */ + +int ALT_EXECVE (char *name, char ** argv, char** env) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(execve); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_exit.c b/software/sys_controller_bsp/HAL/src/alt_exit.c new file mode 100644 index 0000000..971b35e --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_exit.c @@ -0,0 +1,71 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_irq.h" +#include "sys/alt_sim.h" +#include "os/alt_hooks.h" +#include "os/alt_syscall.h" + +#include "alt_types.h" +#include "sys/alt_log_printf.h" +/* + * _exit() is called by exit() in order to terminate the current process. + * Typically this is called when main() completes. It should never return. + * Since there is nowhere to go once this process completes, this + * implementation simply blocks forever. + * + * Note that interrupts are not disabled so that execution outside of this + * thread is allowed to continue. + * + * ALT_EXIT is mapped onto the _exit() system call in alt_syscall.h + */ + +void ALT_EXIT (int exit_code) +{ + /* ALT_LOG - please see HAL/inc/alt_log_printf.h for details */ + ALT_LOG_PRINT_BOOT("[alt_exit.c] Entering _exit() function.\r\n"); + ALT_LOG_PRINT_BOOT("[alt_exit.c] Exit code from main was %d.\r\n",exit_code); + /* Stop all other threads */ + + ALT_LOG_PRINT_BOOT("[alt_exit.c] Calling ALT_OS_STOP().\r\n"); + ALT_OS_STOP(); + + /* Provide notification to the simulator that we've stopped */ + + ALT_LOG_PRINT_BOOT("[alt_exit.c] Calling ALT_SIM_HALT().\r\n"); + ALT_SIM_HALT(exit_code); + + /* spin forever, since there's no where to go back to */ + + ALT_LOG_PRINT_BOOT("[alt_exit.c] Spinning forever.\r\n"); + while (1); +} diff --git a/software/sys_controller_bsp/HAL/src/alt_fcntl.c b/software/sys_controller_bsp/HAL/src/alt_fcntl.c new file mode 100644 index 0000000..69c1544 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_fcntl.c @@ -0,0 +1,101 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include +#include + +#include "sys/alt_errno.h" +#include "priv/alt_file.h" +#include "alt_types.h" +#include "os/alt_syscall.h" + +#define ALT_FCNTL_FLAGS_MASK ((alt_u32) (O_APPEND | O_NONBLOCK)) + +/* + * fcntl() is a limited implementation of the standard fcntl() system call. + * It can be used to change the state of the flags associated with an open + * file descriptor. Normally these flags are set during the call to + * open(). It is anticipated that the main use of this function will be to + * change the state of a device from blocking to non-blocking (where this is + * supported). + * + * The input argument "fd" is the file descriptor to be manipulated. "cmd" + * is the command to execute. This can be either F_GETFL (return the + * current value of the flags) or F_SETFL (set the value of the flags). + * + * If "cmd" is F_SETFL then the argument "arg" is the new value of flags, + * otherwise "arg" is ignored. Only the flags: O_APPEND and O_NONBLOCK + * can be updated by a call to fcntl(). All other flags remain + * unchanged. + * + * ALT_FCNTL is mapped onto the fcntl() system call in alt_syscall.h + */ + +int ALT_FCNTL (int file, int cmd, ...) +{ + alt_fd* fd; + long flags; + va_list argp; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + switch (cmd) + { + case F_GETFL: + return fd->fd_flags & ~((alt_u32) ALT_FD_FLAGS_MASK); + case F_SETFL: + va_start(argp, cmd); + flags = va_arg(argp, long); + fd->fd_flags &= ~ALT_FCNTL_FLAGS_MASK; + fd->fd_flags |= (flags & ALT_FCNTL_FLAGS_MASK); + va_end(argp); + return 0; + default: + ALT_ERRNO = EINVAL; + return -1; + } + } + + ALT_ERRNO = EBADFD; + return -1; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_fd_lock.c b/software/sys_controller_bsp/HAL/src/alt_fd_lock.c new file mode 100644 index 0000000..0e2a85d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_fd_lock.c @@ -0,0 +1,75 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "priv/alt_file.h" + +/* + * alt_fd_lock() is called as a consequence of an ioctl call to gain exclusive + * access to a device, i.e.: + * + * ioctl (fd, TIOCEXCL, NULL); + * + * If there are no other open file descriptors which reference the same + * device, then alt_fd_lock() will grant the lock. Further calls to open() + * for this device will fail until the lock is released. + * + * This is done by calling close() for this file descriptor, or by calling: + * + * ioctl (fd, TIOCNXCL, NULL); + * + * The return value is zero for success, or negative in the case of failure. + */ + +int alt_fd_lock (alt_fd* fd) +{ + int i; + int rc = 0; + + ALT_SEM_PEND(alt_fd_list_lock, 0); + + for (i = 0; i < alt_max_fd; i++) + { + if ((&alt_fd_list[i] != fd) && (alt_fd_list[i].dev == fd->dev)) + { + rc = -EACCES; + goto alt_fd_lock_exit; + } + } + fd->fd_flags |= ALT_FD_EXCL; + + alt_fd_lock_exit: + + ALT_SEM_POST(alt_fd_list_lock); + return rc; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_fd_unlock.c b/software/sys_controller_bsp/HAL/src/alt_fd_unlock.c new file mode 100644 index 0000000..fb700dc --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_fd_unlock.c @@ -0,0 +1,56 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "priv/alt_file.h" + +/* + * alt_fd_unlock() is the inverse of alt_fd_lock(). It is called as a + * consequence of a TIOCNXCL ioctl request, e.g: + * + * ioctl (fd, TIOCNXCL, NULL); + * + * It enables multiple file descriptors to exist for the same device. This + * is normally the case, but it may have been disabled by a previous call to + * alt_fd_lock(). + * + * Return zero on sucess, and a negative value on failure. + * + * The current implementation always succeeds. + */ + +int alt_fd_unlock (alt_fd* fd) +{ + fd->fd_flags &= ~ALT_FD_EXCL; + return 0; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_find_dev.c b/software/sys_controller_bsp/HAL/src/alt_find_dev.c new file mode 100644 index 0000000..37aefa4 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_find_dev.c @@ -0,0 +1,88 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + +#include "alt_types.h" + +/* + * alt_find_dev() is used by open() in order to locate a previously registered + * device with the name "name". The input argument "llist" is a pointer to the + * head of the device list to search. + * + * The return value is a pointer to the matching device, or NULL if there is + * no match. + * + * "name" must be an exact match for the devices registered name for a match to + * be found. + */ + +alt_dev* alt_find_dev(const char* name, alt_llist* llist) +{ + alt_dev* next = (alt_dev*) llist->next; + alt_32 len; + + len = strlen(name) + 1; + + /* + * Check each list entry in turn, until a match is found, or we reach the + * end of the list (i.e. next winds up pointing back to the list head). + */ + + while (next != (alt_dev*) llist) + { + + /* + * memcmp() is used here rather than strcmp() in order to reduce the size + * of the executable. + */ + + if (!memcmp (next->name, name, len)) + { + /* match found */ + + return next; + } + next = (alt_dev*) next->llist.next; + } + + /* No match found */ + + return NULL; +} + + diff --git a/software/sys_controller_bsp/HAL/src/alt_find_file.c b/software/sys_controller_bsp/HAL/src/alt_find_file.c new file mode 100644 index 0000000..2d97ec2 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_find_file.c @@ -0,0 +1,89 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + +#include "alt_types.h" + +/* + * alt_find_file() is used by open() in order to locate a previously registered + * filesystem that owns that mount point that contains the file named "name". + * + * The return value is a pointer to the matching filesystem, or NULL if there is + * no match. + * + * A match is considered to have been found if the filesystem name followed by + * either '/' or '\0' is the prefix of the filename. For example the filename: + * "/myfilesystem/junk.txt" would match: "/myfilesystem", but not: "/myfile". + */ + +alt_dev* alt_find_file (const char* name) +{ + alt_dev* next = (alt_dev*) alt_fs_list.next; + + alt_32 len; + + /* + * Check each list entry in turn, until a match is found, or we reach the + * end of the list (i.e. next winds up pointing back to the list head). + */ + + while (next != (alt_dev*) &alt_fs_list) + { + len = strlen(next->name); + + if (next->name[len-1] == '/') + { + len -= 1; + } + + if (((name[len] == '/') || (name[len] == '\0')) && + !memcmp (next->name, name, len)) + { + /* match found */ + + return next; + } + next = (alt_dev*) next->llist.next; + } + + /* No match found */ + + return NULL; +} + + diff --git a/software/sys_controller_bsp/HAL/src/alt_flash_dev.c b/software/sys_controller_bsp/HAL/src/alt_flash_dev.c new file mode 100644 index 0000000..213f721 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_flash_dev.c @@ -0,0 +1,69 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/****************************************************************************** +* * +* Alt_flash.c - Functions to register a flash device to the "generic" flash * +* interface * +* * +* Author PRR * +* * +******************************************************************************/ + +#include +#include "sys/alt_llist.h" +#include "sys/alt_flash_dev.h" +#include "priv/alt_file.h" + +ALT_LLIST_HEAD(alt_flash_dev_list); + +alt_flash_fd* alt_flash_open_dev(const char* name) +{ + alt_flash_dev* dev = (alt_flash_dev*)alt_find_dev(name, &alt_flash_dev_list); + + if ((dev) && dev->open) + { + return dev->open(dev, name); + } + + return dev; +} + +void alt_flash_close_dev(alt_flash_fd* fd) +{ + if (fd && fd->close) + { + fd->close(fd); + } + return; +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_fork.c b/software/sys_controller_bsp/HAL/src/alt_fork.c new file mode 100644 index 0000000..ce74df0 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_fork.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_warning.h" +#include "sys/alt_errno.h" +#include "os/alt_syscall.h" + +/* + * The fork() system call is used by newlib to create a duplicate copy of the + * curent process. This is unsupported in the HAL environment. However a + * "do-nothing" implementation is still provied for newlib compatability. + * + * ALT_FORK is mapped onto the fork() system call in alt_syscall.h + */ + +int ALT_FORK (void) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(fork); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} + + diff --git a/software/sys_controller_bsp/HAL/src/alt_fs_reg.c b/software/sys_controller_bsp/HAL/src/alt_fs_reg.c new file mode 100644 index 0000000..13437a1 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_fs_reg.c @@ -0,0 +1,75 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + +/* + * The alt_fs_reg() function is used to register a file system. Once registered + * a device can be accessed using the standard posix calls: open(), read(), + * write() etc. + * + * System behaviour is undefined in the event that a file system is registered + * with a name that conflicts with an existing device or file system. + * + * alt_fs_reg() is not thread safe in the sense that there should be no other + * thread using the file system list at the time that alt_dev_reg() is called. In + * practice this means that alt_fs_reg() should only be called while operating + * in a single threaded mode. The expectation is that it will only be called + * by the file system initilisation functions invoked by alt_sys_init(), which in + * turn should only be called by the single threaded C startup code. + * + * A return value of zero indicates success. A negative return value indicates + * failure. + */ + +int alt_fs_reg (alt_dev* dev) +{ + /* + * check that the device has a name. + */ + + if (!dev->name) + { + return -ENODEV; + } + + /* + * register the file system. + */ + + alt_llist_insert(&alt_fs_list, &dev->llist); + + return 0; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_fstat.c b/software/sys_controller_bsp/HAL/src/alt_fstat.c new file mode 100644 index 0000000..af5d527 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_fstat.c @@ -0,0 +1,128 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include "sys/alt_dev.h" +#include "sys/alt_warning.h" +#include "sys/alt_errno.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +/* + * The fstat() system call is used to obtain information about the capabilities + * of an open file descriptor. By default file descriptors are marked as + * being character devices. If a device or file system wishes to advertise + * alternative capabilities then they can register an fstat() function within + * their associated alt_dev structure. This will be called to fill in the + * entries in the imput "st" structure. + * + * This function is provided for compatability with newlib. + * + * ALT_FSTAT is mapped onto the fstat() system call in alt_syscall.h + */ + +#ifdef ALT_USE_DIRECT_DRIVERS + +#include "system.h" + +/* + * Provide minimal version that just describes all file descriptors + * as character devices for provided stdio devices. + */ +int ALT_FSTAT (int file, struct stat *st) +{ + switch (file) { +#ifdef ALT_STDIN_PRESENT + case 0: /* stdin file descriptor */ +#endif /* ALT_STDIN_PRESENT */ +#ifdef ALT_STDOUT_PRESENT + case 1: /* stdout file descriptor */ +#endif /* ALT_STDOUT_PRESENT */ +#ifdef ALT_STDERR_PRESENT + case 2: /* stderr file descriptor */ +#endif /* ALT_STDERR_PRESENT */ + st->st_mode = _IFCHR; + return 0; + default: + return -1; + } + +#if !defined(ALT_STDIN_PRESENT) && !defined(ALT_STDOUT_PRESENT) && !defined(ALT_STDERR_PRESENT) + /* Generate a link time warning, should this function ever be called. */ + ALT_STUB_WARNING(fstat); +#endif +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +int ALT_FSTAT (int file, struct stat *st) +{ + alt_fd* fd; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + /* Call the drivers fstat() function to fill out the "st" structure. */ + + if (fd->dev->fstat) + { + return fd->dev->fstat(fd, st); + } + + /* + * If no function is provided, mark the fd as belonging to a character + * device. + */ + + else + { + st->st_mode = _IFCHR; + return 0; + } + } + else + { + ALT_ERRNO = EBADFD; + return -1; + } +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_get_fd.c b/software/sys_controller_bsp/HAL/src/alt_get_fd.c new file mode 100644 index 0000000..db17b2c --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_get_fd.c @@ -0,0 +1,105 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + +#include "alt_types.h" + +#include "system.h" + +/* + * alt_get_fd() is called to allocate a new file descriptor from the file + * descriptor pool. If a file descriptor is succesfully allocated, it is + * configured to refer to device "dev". + * + * The return value is the index of the file descriptor structure (i.e. + * the offset of the file descriptor within the file descriptor array). A + * negative value indicates failure. + */ + +int alt_get_fd (alt_dev* dev) +{ + alt_32 i; + int rc = -EMFILE; + + /* + * Take the alt_fd_list_lock semaphore in order to avoid races when + * accessing the file descriptor pool. + */ + + ALT_SEM_PEND(alt_fd_list_lock, 0); + + /* + * Search through the list of file descriptors, and allocate the first + * free descriptor that's found. + * + * If a free descriptor is found, then the value of "alt_max_fd" is + * updated accordingly. "alt_max_fd" is a 'highwater mark' which + * indicates the highest file descriptor ever allocated. This is used to + * improve efficency when searching the file descriptor list, and + * therefore reduce contention on the alt_fd_list_lock semaphore. + */ + + for (i = 0; i < ALT_MAX_FD; i++) + { + if (!alt_fd_list[i].dev) + { + alt_fd_list[i].dev = dev; + if (i > alt_max_fd) + { + alt_max_fd = i; + } + rc = i; + goto alt_get_fd_exit; + } + } + + alt_get_fd_exit: + + /* + * Release the alt_fd_list_lock semaphore now that we are done with the + * file descriptor pool. + */ + + ALT_SEM_POST(alt_fd_list_lock); + + return rc; +} + + + + diff --git a/software/sys_controller_bsp/HAL/src/alt_getchar.c b/software/sys_controller_bsp/HAL/src/alt_getchar.c new file mode 100644 index 0000000..551b00a --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_getchar.c @@ -0,0 +1,70 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#ifdef ALT_USE_DIRECT_DRIVERS +#include "system.h" +#include "sys/alt_driver.h" +#include "sys/alt_stdio.h" +#include "priv/alt_file.h" +#include "unistd.h" +#endif +#ifdef ALT_SEMIHOSTING +#include "sys/alt_stdio.h" +#include "unistd.h" +#endif +/* + * Uses the ALT_DRIVER_READ() macro to call directly to driver if available. + * Otherwise, uses newlib provided getchar() routine. + */ +int +alt_getchar(void) +{ +#ifdef ALT_SEMIHOSTING + char c; + read(STDIN_FILENO,&c,1); + return c; +#else +#ifdef ALT_USE_DIRECT_DRIVERS + ALT_DRIVER_READ_EXTERNS(ALT_STDIN_DEV); + char c; + + if (ALT_DRIVER_READ(ALT_STDIN_DEV, &c, 1, alt_fd_list[STDIN_FILENO].fd_flags) <= 0) { + return -1; + } + return c; +#else + return getchar(); +#endif +#endif +} diff --git a/software/sys_controller_bsp/HAL/src/alt_getpid.c b/software/sys_controller_bsp/HAL/src/alt_getpid.c new file mode 100644 index 0000000..2228c7e --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_getpid.c @@ -0,0 +1,47 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "os/alt_syscall.h" + +/* + * The getpid() system call is used by newlib to obtain the current process + * id. Since there is only ever a single process in the HAL environment, + * this just returns a constant. + * + * ALT_GETPID is mapped onto the getpid() system call in alt_syscall.h + */ + +int ALT_GETPID (void) +{ + return 0; +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_gettod.c b/software/sys_controller_bsp/HAL/src/alt_gettod.c new file mode 100644 index 0000000..ed86cba --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_gettod.c @@ -0,0 +1,125 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include + +#include "sys/alt_alarm.h" +#include "alt_types.h" +#include "os/alt_syscall.h" + +/* + * Macro defining the number of micoseconds in a second. + */ + +#define ALT_US (1000000) + +/* + * "alt_timezone" and "alt_resettime" are the values of the the reset time and + * time zone set through the last call to settimeofday(). By default they are + * zero initialised. + */ + +struct timezone alt_timezone = {0, 0}; +struct timeval alt_resettime = {0, 0}; + +/* + * gettimeofday() can be called to obtain a time structure which indicates the + * current "wall clock" time. This is calculated using the elapsed number of + * system clock ticks, and the value of "alt_resettime" and "alt_timezone" set + * through the last call to settimeofday(). + * + * Warning: if this function is called concurrently with a call to + * settimeofday(), the value returned by gettimeofday() will be unreliable. + * + * ALT_GETTIMEOFDAY is mapped onto the gettimeofday() system call in + * alt_syscall.h + */ + + +#if defined (__GNUC__) && (__GNUC__ >= 4) +int ALT_GETTIMEOFDAY (struct timeval *ptimeval, void *ptimezone_vptr) +{ + struct timezone *ptimezone = (struct timezone*)ptimezone_vptr; +#else +int ALT_GETTIMEOFDAY (struct timeval *ptimeval, struct timezone *ptimezone) +{ +#endif + + alt_u32 nticks = alt_nticks (); + alt_u32 tick_rate = alt_ticks_per_second (); + + /* + * Check to see if the system clock is running. This is indicated by a + * non-zero system clock rate. If the system clock is not running, an error + * is generated and the contents of "ptimeval" and "ptimezone" are not + * updated. + */ + + if (tick_rate) + { + ptimeval->tv_sec = alt_resettime.tv_sec + nticks/tick_rate; + ptimeval->tv_usec = alt_resettime.tv_usec + + (alt_u32)(((alt_u64)nticks*(ALT_US/tick_rate))%ALT_US); + + while(ptimeval->tv_usec < 0) { + if (ptimeval->tv_sec <= 0) + { + ptimeval->tv_sec = 0; + ptimeval->tv_usec = 0; + break; + } + else + { + ptimeval->tv_sec--; + ptimeval->tv_usec += ALT_US; + } + } + + while(ptimeval->tv_usec >= ALT_US) { + ptimeval->tv_sec++; + ptimeval->tv_usec -= ALT_US; + } + + if (ptimezone) + { + ptimezone->tz_minuteswest = alt_timezone.tz_minuteswest; + ptimezone->tz_dsttime = alt_timezone.tz_dsttime; + } + + return 0; + } + + return -ENOTSUP; +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_gmon.c b/software/sys_controller_bsp/HAL/src/alt_gmon.c new file mode 100644 index 0000000..6add9f1 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_gmon.c @@ -0,0 +1,272 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include + +#include "priv/nios2_gmon_data.h" + +#include "sys/alt_irq.h" +#include "sys/alt_alarm.h" + + +/* Macros */ + +/* How large should the bins be which we use to generate the histogram */ +#define PCSAMPLE_BYTES_PER_BUCKET 32 + +#define NIOS2_READ_EA(dest) __asm__ ("mov %0, ea" : "=r" (dest)) + +/* The compiler inserts calls to mcount() at the start of + * every function call. The structure mcount_fn_arc records t + * he return address of the function called (in from_pc) + * and the return address of the mcount function + * (in self_pc). The number of times this arc is executed is + * recorded in the field count. + */ +struct mcount_fn_arc +{ + struct mcount_fn_arc * next; + void * from_pc; + unsigned int count; +}; + +/* We need to maintain a list of pointers to the heads of each adjacency + * list so that we can find them when writing out the gmon.out file. Since + * we don't know at the start of program execution how many functions will + * be called we use a list structure to do this. + */ +struct mcount_fn_entry +{ + struct mcount_fn_entry * next; + void * self_pc; + struct mcount_fn_arc * arc_head; +}; + +/* function prototypes */ + +void __mcount_record(void * self_pc, void * from_pc, struct mcount_fn_entry * fn_entry, struct mcount_fn_entry * * fn_head) __attribute__ ((no_instrument_function)); + +static __inline__ void * mcount_allocate(unsigned int size) __attribute__ ((no_instrument_function)); +static int nios2_pcsample_init(void) __attribute__ ((no_instrument_function)); +static alt_u32 nios2_pcsample(void* alarm) __attribute__ ((no_instrument_function)); + +/* global variables */ + +/* stext and etext are defined in the linker script */ +extern char stext[]; +extern char etext[]; + +/* Is the PC sampling stuff enabled yet? */ +static int pcsample_need_init = 1; + +#define HASH_BUCKETS 64 /* Must be a power of 2 */ + +/* This points to the list of adjacency list pointers. */ +struct mcount_fn_entry * __mcount_fn_head[HASH_BUCKETS]; + +/* pointer to the in-memory buffer containing the histogram */ +static unsigned short* s_pcsamples = 0; + +/* the address of the start and end of text section */ +static const unsigned int s_low_pc = (unsigned int)stext; +static const unsigned int s_high_pc = (unsigned int)etext; + +/* the alarm structure to register for pc sampling */ +static alt_alarm s_nios2_pcsample_alarm; + +unsigned int alt_gmon_data[GMON_DATA_SIZE] = +{ + 0x6e6f6d67, /* "gmon" */ + GMON_DATA_SIZE, + 0, + (unsigned int)stext, + (unsigned int)etext, + PCSAMPLE_BYTES_PER_BUCKET, + 0, + (unsigned int)__mcount_fn_head, + (unsigned int)(__mcount_fn_head + HASH_BUCKETS) +}; + +/* This holds the current slab of memory we're allocating out of */ +static char * mcount_slab_ptr = 0; +static int mcount_slab_size = 0; + +#define MCOUNT_SLAB_INCREMENT 1020 + + +/* + * We can't use malloc to allocate memory because that's too complicated, and + * can't be called at interrupt time. Use the lower level allocator instead + * because that's interrupt safe (and because we never free anything). + * + * For speed, we allocate a block of data at once. + */ +static __inline__ void * mcount_allocate(unsigned int size) +{ + void * data; + + if (size > mcount_slab_size) + { + mcount_slab_ptr = sbrk(MCOUNT_SLAB_INCREMENT); + mcount_slab_size = MCOUNT_SLAB_INCREMENT; + } + + data = mcount_slab_ptr; + mcount_slab_ptr += size; + mcount_slab_size -= size; + + return data; +} + + +/* + * Add the arc with the values of frompc and topc given to the graph. + * This function might be called at interrupt time so must be able to + * cope with reentrancy. + * + * The fast case, where we have already allocated a function arc, has been + * handled by the assmebler code. + */ +void __mcount_record(void * self_pc, void * from_pc, struct mcount_fn_entry * fn_entry, struct mcount_fn_entry * * fn_head) +{ + alt_irq_context context; + struct mcount_fn_arc * arc_entry; + + /* Keep trying to start up the PC sampler until it is running. + * (It can't start until the timer is going). + */ + if (pcsample_need_init) + { + pcsample_need_init = 0; + pcsample_need_init = nios2_pcsample_init(); + } + + /* + * We must disable interrupts around the allocation and the list update to + * prevent corruption if the instrumented function is re-entrant. + * + * It's safe for the code above to be stepping through the chain and be + * interrupted by this code modifying it - there is an edge case which will + * leave two copies of the same arc on the list (both with count=1), but + * this is dealt with on the host. + */ + context = alt_irq_disable_all(); + + if (fn_entry == NULL) + { + /* Add it to the list of functions we must output later. */ + fn_entry = (struct mcount_fn_entry *)mcount_allocate(sizeof(struct mcount_fn_entry)); + + fn_entry->self_pc = self_pc; + fn_entry->arc_head = NULL; + + fn_entry->next = *fn_head; + *fn_head = fn_entry; + } + + /* We will need a new list entry - if there was a list entry before + * then the assembler code would have handled it. */ + arc_entry = (struct mcount_fn_arc *)mcount_allocate(sizeof(struct mcount_fn_arc)); + + arc_entry->from_pc = from_pc; + arc_entry->count = 1; + + arc_entry->next = fn_entry->arc_head; + fn_entry->arc_head = arc_entry; + + alt_irq_enable_all(context); +} + + +/* + * nios2_pcsample_init starts profiling. + * It is called the first time mcount is called, and on subsequent calls to + * mcount until it returns zero. It initializes the pc histogram and turns on + * timer driven pc sampling. + */ +static int nios2_pcsample_init(void) +{ + unsigned int pcsamples_size; + + /* We sample the PC every tick */ + unsigned int prof_rate = alt_ticks_per_second(); + if (prof_rate == 0) + return 1; + + /* allocate the histogram buffer s_pcsamples */ + pcsamples_size = (s_high_pc - s_low_pc)/PCSAMPLE_BYTES_PER_BUCKET; + s_pcsamples = (unsigned short*)sbrk(pcsamples_size * sizeof(unsigned short)); + + if (s_pcsamples != 0) + { + /* initialize the buffer to zero */ + memset(s_pcsamples, 0, pcsamples_size * sizeof(unsigned short)); + + alt_gmon_data[GMON_DATA_PROFILE_DATA] = (int)s_pcsamples; + alt_gmon_data[GMON_DATA_PROFILE_RATE] = prof_rate; + + /* Sample every tick (it's cheap) */ + alt_alarm_start(&s_nios2_pcsample_alarm, 1, nios2_pcsample, 0); + } + + return 0; +} + + +/* + * Sample the PC value and store it in the histogram + */ +static alt_u32 nios2_pcsample(void* context) +{ + unsigned int pc; + unsigned int bucket; + + /* read the exception return address - this will be + * inaccurate if there are nested interrupts but we + * assume that this is rare and the inaccuracy will + * not be great */ + NIOS2_READ_EA(pc); + + /* + * If we're within the profilable range then increment the relevant + * bucket in the histogram + */ + if (pc >= s_low_pc && pc < s_high_pc && s_pcsamples != 0) + { + bucket = (pc - s_low_pc)/PCSAMPLE_BYTES_PER_BUCKET; + s_pcsamples[bucket]++; + } + + /* Sample every tick */ + return 1; +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_icache_flush.c b/software/sys_controller_bsp/HAL/src/alt_icache_flush.c new file mode 100644 index 0000000..4b706ed --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_icache_flush.c @@ -0,0 +1,84 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "nios2.h" +#include "system.h" + +#include "alt_types.h" +#include "sys/alt_cache.h" + +/* + * alt_icache_flush() is called to flush the instruction cache for a memory + * region of length "len" bytes, starting at address "start". + */ + +void alt_icache_flush (void* start, alt_u32 len) +{ +#if NIOS2_ICACHE_SIZE > 0 + + char* i; + char* end; + + /* + * This is the most we would ever need to flush. + */ + + if (len > NIOS2_ICACHE_SIZE) + { + len = NIOS2_ICACHE_SIZE; + } + + end = ((char*) start) + len; + + for (i = start; i < end; i+= NIOS2_ICACHE_LINE_SIZE) + { + __asm__ volatile ("flushi %0" :: "r" (i)); + } + + /* + * For an unaligned flush request, we've got one more line left. + * Note that this is dependent on NIOS2_ICACHE_LINE_SIZE to be a + * multiple of 2 (which it always is). + */ + + if (((alt_u32) start) & (NIOS2_ICACHE_LINE_SIZE - 1)) + { + __asm__ volatile ("flushi %0" :: "r" (i)); + } + + /* + * Having flushed the cache, flush any stale instructions in the + * pipeline + */ + + __asm__ volatile ("flushp"); + +#endif /* NIOS2_ICACHE_SIZE > 0 */ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_icache_flush_all.c b/software/sys_controller_bsp/HAL/src/alt_icache_flush_all.c new file mode 100644 index 0000000..5088552 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_icache_flush_all.c @@ -0,0 +1,46 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "nios2.h" +#include "system.h" + +#include "alt_types.h" +#include "sys/alt_cache.h" + +/* + * alt_icache_flush_all() is called to flush the entire instruction cache. + */ + +void alt_icache_flush_all (void) +{ +#if NIOS2_ICACHE_SIZE > 0 + alt_icache_flush (0, NIOS2_ICACHE_SIZE); +#endif +} diff --git a/software/sys_controller_bsp/HAL/src/alt_iic.c b/software/sys_controller_bsp/HAL/src/alt_iic.c new file mode 100644 index 0000000..1db5afa --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_iic.c @@ -0,0 +1,106 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ +#include "system.h" + +/* + * This file implements the HAL Enhanced interrupt API for Nios II processors + * with an internal interrupt controller (IIC). For most routines, this serves + * as a wrapper layer over the legacy interrupt API (which must be used with + * the IIC only). + * + * Use of the enhanced API is recommended so that application and device + * drivers are compatible with a Nios II system configured with an external + * interrupt controller (EIC), or IIC. This will afford maximum portability. + * + * If an EIC is present, the EIC device driver must provide these routines, + * because their operation will be specific to that EIC type. + */ +#ifndef NIOS2_EIC_PRESENT +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + +#include "sys/alt_irq.h" +#include "priv/alt_iic_isr_register.h" +#include "priv/alt_legacy_irq.h" + +/** @Function Description: This function registers an interrupt handler. + * If the function is succesful, then the requested interrupt will be enabled upon + * return. Registering a NULL handler will disable the interrupt. + * @API Type: External + * @param ic_id Ignored. + * @param irq IRQ number + * @return 0 if successful, else error (-1) + */ +int alt_ic_isr_register(alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, + void *isr_context, void *flags) +{ + return alt_iic_isr_register(ic_id, irq, isr, isr_context, flags); +} + +/** @Function Description: This function enables a single interrupt. + * @API Type: External + * @param ic_id Ignored. + * @param irq IRQ number + * @return 0 if successful, else error (-1) + */ +int alt_ic_irq_enable (alt_u32 ic_id, alt_u32 irq) +{ + return alt_irq_enable(irq); +} + +/** @Function Description: This function disables a single interrupt. + * @API Type: External + * @param ic_id Ignored. + * @param irq IRQ number + * @return 0 if successful, else error (-1) + */ +int alt_ic_irq_disable(alt_u32 ic_id, alt_u32 irq) +{ + return alt_irq_disable(irq); +} + +/** @Function Description: This function to determine if corresponding + * interrupt is enabled. + * @API Type: External + * @param ic_id Ignored. + * @param irq IRQ number + * @return Zero if corresponding interrupt is disabled and + * non-zero otherwise. + */ +alt_u32 alt_ic_irq_enabled(alt_u32 ic_id, alt_u32 irq) +{ + alt_u32 irq_enabled; + + NIOS2_READ_IENABLE(irq_enabled); + + return (irq_enabled & (1 << irq)) ? 1: 0; +} + +#endif /* ALT_ENHANCED_INTERRUPT_API_PRESENT */ +#endif /* NIOS2_EIC_PRESENT */ diff --git a/software/sys_controller_bsp/HAL/src/alt_iic_isr_register.c b/software/sys_controller_bsp/HAL/src/alt_iic_isr_register.c new file mode 100644 index 0000000..b104395 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_iic_isr_register.c @@ -0,0 +1,104 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ +#include +#include "system.h" + +/* + * Provides an interrupt registry mechanism for the any CPUs internal interrupt + * controller (IIC) when the enhanced interrupt API is active. + */ +#ifndef ALT_CPU_EIC_PRESENT +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + +#include "alt_types.h" +#include "sys/alt_irq.h" +#include "priv/alt_iic_isr_register.h" + +/* + * The header, alt_irq_entry.h, contains the exception entry point, and is + * provided by the processor component. It is included here, so that the code + * will be added to the executable only if alt_irq_register() is present, i.e. + * if no interrupts are registered - there's no need to provide any + * interrupt handling. + */ + +#include "sys/alt_irq_entry.h" + +/* + * The header, alt_irq_table.h contains a table describing which function + * handles each interrupt. + */ + +#include "priv/alt_irq_table.h" + +/** @Function Description: This function registers an interrupt handler. + * If the function is succesful, then the requested interrupt will be enabled + * upon return. Registering a NULL handler will disable the interrupt. + * + * @API Type: External + * @param ic_id Interrupt controller ID + * @param irq IRQ ID number + * @param isr Pointer to interrupt service routine + * @param isr_context Opaque pointer passed to ISR + * @param flags + * @return 0 if successful, else error (-1) + */ +int alt_iic_isr_register(alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, + void *isr_context, void *flags) +{ + int rc = -EINVAL; + int id = irq; /* IRQ interpreted as the interrupt ID. */ + alt_irq_context status; + + if (id < ALT_NIRQ) + { + /* + * interrupts are disabled while the handler tables are updated to ensure + * that an interrupt doesn't occur while the tables are in an inconsistant + * state. + */ + + status = alt_irq_disable_all(); + + alt_irq[id].handler = isr; + alt_irq[id].context = isr_context; + + rc = (isr) ? alt_ic_irq_enable(ic_id, id) : alt_ic_irq_disable(ic_id, id); + + alt_irq_enable_all(status); + } + + return rc; +} + +#endif /* ALT_ENHANCED_INTERRUPT_API_PRESENT */ +#endif /* ALT_CPU_EIC_PRESENT */ diff --git a/software/sys_controller_bsp/HAL/src/alt_instruction_exception_entry.c b/software/sys_controller_bsp/HAL/src/alt_instruction_exception_entry.c new file mode 100644 index 0000000..214f7af --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_instruction_exception_entry.c @@ -0,0 +1,206 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ +#include "sys/alt_exceptions.h" +#include "nios2.h" +#include "alt_types.h" +#include "system.h" + +/* + * This file implements support for calling user-registered handlers for + * instruction-generated exceptions. This handler could also be reached + * in the event of a spurious interrupt. + * + * The handler code is optionally enabled through the "Enable + * Instruction-related Exception API" HAL BSP setting, which will + * define the macro below. + */ +#ifdef ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API + +/* Function pointer to exception callback routine */ +alt_exception_result (*alt_instruction_exception_handler) + (alt_exception_cause, alt_u32, alt_u32) = 0x0; + +/* Link entry routine to .exceptions section */ +int alt_instruction_exception_entry (alt_u32 exception_pc) + __attribute__ ((section (".exceptions"))); + +/* + * This is the entry point for instruction-generated exceptions handling. + * This routine will be called by alt_exceptions_entry.S, after it determines + * that an exception could not be handled by handlers that preceed that + * of instruction-generated exceptions (such as interrupts). + * + * For this to function properly, you must register an exception handler + * using alt_instruction_exception_register(). This routine will call + * that handler if it has been registered. Absent a handler, it will + * break break or hang as discussed below. + */ +int +alt_instruction_exception_entry (alt_u32 exception_pc) +{ + alt_u32 cause, badaddr; + +/* + * If the processor hardware has the optional EXCEPTIONS & BADADDR registers, + * read them and pass their content to the user handler. These are always + * present if the MMU or MPU is enabled, and optionally for other advanced + * exception types via the "Extra exceptions information" setting in the + * processor (hardware) configuration. + * + * If these registers are not present, the cause field will be set to + * NIOS2_EXCEPTION_CAUSE_NOT_PRESENT. Your handling routine should + * check the validity of the cause argument before proceeding. + */ +#ifdef NIOS2_HAS_EXTRA_EXCEPTION_INFO + /* Get exception cause & "badaddr" */ + NIOS2_READ_EXCEPTION(cause); + cause = ( (cause & NIOS2_EXCEPTION_REG_CAUSE_MASK) >> + NIOS2_EXCEPTION_REG_CAUSE_OFST ); + + NIOS2_READ_BADADDR(badaddr); +#else + cause = NIOS2_EXCEPTION_CAUSE_NOT_PRESENT; + badaddr = 0; +#endif /* NIOS2_HAS_EXTRA_EXCEPTION_INFO */ + + if(alt_instruction_exception_handler) { + /* + * Call handler. Its return value indicates whether the exception-causing + * instruction should be re-issued. The code that called us, + * alt_eceptions_entry.S, will look at this value and adjust the ea + * register as necessary + */ + return alt_instruction_exception_handler(cause, exception_pc, badaddr); + } + /* + * We got here because an instruction-generated exception occured, but no + * handler is present. We do not presume to know how to handle it. If the + * debugger is present, break, otherwise hang. + * + * If you've reached here in the debugger, consider examining the + * EXCEPTIONS register cause bit-field, which was read into the 'cause' + * variable above, and compare it against the exceptions-type enumeration + * in alt_exceptions.h. This register is availabe if the MMU or MPU is + * present, or if the "Extra exceptions information" hardware option is + * selected. + * + * If you get here then one of the following could have happened: + * + * - An instruction-generated exception occured, and the processor + * does not have the extra exceptions feature enabled, or you + * have not registered a handler using + * alt_instruction_exception_register() + * + * Some examples of instruction-generated exceptions and why they + * might occur: + * + * - Your program could have been compiled for a full-featured + * Nios II core, but it is running on a smaller core, and + * instruction emulation has been disabled by defining + * ALT_NO_INSTRUCTION_EMULATION. + * + * You can work around the problem by re-enabling instruction + * emulation, or you can figure out why your program is being + * compiled for a system other than the one that it is running on. + * + * - Your program has executed a trap instruction, but has not + * implemented a handler for this instruction. + * + * - Your program has executed an illegal instruction (one which is + * not defined in the instruction set). + * + * - Your processor includes an MMU or MPU, and you have enabled it + * before registering an exception handler to service exceptions it + * generates. + * + * The problem could also be hardware related: + * - If your hardware is broken and is generating spurious interrupts + * (a peripheral which negates its interrupt output before its + * interrupt handler has been executed will cause spurious interrupts) + */ + else { +#ifdef NIOS2_HAS_DEBUG_STUB + NIOS2_BREAK(); +#else + while(1) + ; +#endif /* NIOS2_HAS_DEBUG_STUB */ + } + + /* We should not get here. Remove compiler warning. */ + return NIOS2_EXCEPTION_RETURN_REISSUE_INST; +} + +#endif /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API */ + +/* + * This routine indicates whether a particular exception cause will have + * set a valid address into the BADADDR register, which is included + * in the arguments to a user-registered instruction-generated exception + * handler. Many exception types do not set valid contents in BADADDR; + * this is a convenience routine to easily test the validity of that + * argument in your handler. + * + * Note that this routine will return false (0) for causes + * NIOS2_EXCEPTION_TLB_MISS and NIOS2_EXCEPTION_ECC_TLB_ERR. + * You must read the TLBMISC.D field to determine if BADADDR + * is valid for these (valid if TLBMISC.D = 1). + * + * Arguments: + * cause: The 5-bit exception cause field of the EXCEPTIONS register, + * shifted to the LSB position. You may pass the 'cause' argument + * in a handler you registered directy to this routine. + * + * Return: 1: BADADDR (bad_addr argument to handler) is valid + * 0: BADADDR is not valid + */ +int +alt_exception_cause_generated_bad_addr(alt_exception_cause cause) +{ + switch (cause) { + case NIOS2_EXCEPTION_SUPERVISOR_ONLY_DATA_ADDR: + case NIOS2_EXCEPTION_MISALIGNED_DATA_ADDR: + case NIOS2_EXCEPTION_MISALIGNED_TARGET_PC: + case NIOS2_EXCEPTION_TLB_READ_PERM_VIOLATION: + case NIOS2_EXCEPTION_TLB_WRITE_PERM_VIOLATION: + case NIOS2_EXCEPTION_MPU_DATA_REGION_VIOLATION: + case NIOS2_EXCEPTION_ECC_DATA_ERR: + return 1; + + case NIOS2_EXCEPTION_TLB_MISS: + case NIOS2_EXCEPTION_ECC_TLB_ERR: + return 0; + + default: + return 0; + } +} diff --git a/software/sys_controller_bsp/HAL/src/alt_instruction_exception_register.c b/software/sys_controller_bsp/HAL/src/alt_instruction_exception_register.c new file mode 100644 index 0000000..b059e1d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_instruction_exception_register.c @@ -0,0 +1,82 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ +#include "sys/alt_exceptions.h" +#include "alt_types.h" +#include "system.h" + +/* + * This file implements support for calling user-registered handlers for + * instruction-generated exceptions. + * + * The registry API is optionally enabled through the "Enable + * Instruction-related Exception API" HAL BSP setting, which will + * define the macro below. + */ +#ifdef ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API + +/* + * The header, alt_exception_handler_registry.h contains a struct describing + * the registered exception handler + */ +#include "priv/alt_exception_handler_registry.h" + +/* + * Pull in the exception entry assembly code. This will not be linked in + * unless this object is linked into the executable (i.e. only if + * alt_instruction_exception_register() is called). + */ +__asm__( "\n\t.globl alt_exception" ); + +/* + * alt_instruction_exception_register() is called to register a handler to + * service instruction-generated exceptions that are not handled by the + * default exception handler code (interrupts, and optionally unimplemented + * instructions and traps). + * + * Passing null (0x0) in the handler argument will disable a previously- + * registered handler. + * + * Note that if no handler is registered, exceptions that are not processed + * using the built-in handler (interrupts, and optionally unimplemented + * instructions and traps) are treated as unknown exceptions, resulting + * in either a break or an infinite loop. + */ +void alt_instruction_exception_register ( + alt_exception_result (*exception_handler)( + alt_exception_cause cause, + alt_u32 exception_pc, + alt_u32 bad_addr) ) +{ + alt_instruction_exception_handler = exception_handler; +} + +#endif /* ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API */ diff --git a/software/sys_controller_bsp/HAL/src/alt_io_redirect.c b/software/sys_controller_bsp/HAL/src/alt_io_redirect.c new file mode 100644 index 0000000..8c862f7 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_io_redirect.c @@ -0,0 +1,98 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include +#include + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + + +/* + * alt_open_fd() is similar to open() in that it is used to obtain a file + * descriptor for the file named "name". The "flags" and "mode" arguments are + * identical to the "flags" and "mode" arguments of open(). + * + * The distinction between the two functions is that the file descriptor + * structure to use is passed in as an argument, rather than allocated from the + * list of free file descriptors. + * + * This is used by alt_io_redirect() to redirect the stdin, stdout and stderr + * file descriptors to point to new devices. + * + * If the device can not be succesfully opened, then the input file descriptor + * remains unchanged. + */ + +static void alt_open_fd(alt_fd* fd, const char* name, int flags, int mode) +{ + int old; + + old = open (name, flags, mode); + + if (old >= 0) + { + fd->dev = alt_fd_list[old].dev; + fd->priv = alt_fd_list[old].priv; + fd->fd_flags = alt_fd_list[old].fd_flags; + + alt_release_fd (old); + } +} + +/* + * alt_io_redirect() is called once the device/filesystem lists have been + * initialised, but before main(). Its function is to redirect standard in, + * standard out and standard error so that they point to the devices selected by + * the user (as defined in system.h). + * + * Prior to the call to this function, io is directed towards /dev/null. If + * i/o can not be redirected to the requested device, for example if the device + * does not exist, then it remains directed at /dev/null. + */ + +void alt_io_redirect(const char* stdout_dev, + const char* stdin_dev, + const char* stderr_dev) +{ + /* Redirect the channels */ + + alt_open_fd (&alt_fd_list[STDOUT_FILENO], stdout_dev, O_WRONLY, 0777); + alt_open_fd (&alt_fd_list[STDIN_FILENO], stdin_dev, O_RDONLY, 0777); + alt_open_fd (&alt_fd_list[STDERR_FILENO], stderr_dev, O_WRONLY, 0777); +} + + + + diff --git a/software/sys_controller_bsp/HAL/src/alt_ioctl.c b/software/sys_controller_bsp/HAL/src/alt_ioctl.c new file mode 100644 index 0000000..f5d7ef1 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_ioctl.c @@ -0,0 +1,170 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "sys/ioctl.h" +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +/* + * The ioctl() system call is provided so that application code can manipulate + * the i/o capabilities of a device in device specific ways. This is identical + * to the standard posix ioctl() function. + * + * In general this implementation simply vectors ioctl requests to the + * apropriate drivers ioctl function (as registered in the drivers alt_dev + * structure). + * + * However in the case of devices (as oposed to filesystem), the TIOCEXCL and + * TIOCNXCL requests are handled without reference to the driver. These + * requests are used to lock/release a device for exclusive access. + * + * Handling these requests centrally eases the task of device driver + * development. + * + * ALT_IOCTL is mapped onto the ioctl() system call in alt_syscall.h + */ + +#ifdef ALT_USE_DIRECT_DRIVERS + +#include "system.h" +#include "sys/alt_driver.h" + +/* + * Provide minimal version that calls ioctl routine of provided stdio devices. + */ +int ALT_IOCTL (int file, int req, void* arg) +{ +#ifdef ALT_STDIN_PRESENT + ALT_DRIVER_IOCTL_EXTERNS(ALT_STDIN_DEV); +#endif +#ifdef ALT_STDOUT_PRESENT + ALT_DRIVER_IOCTL_EXTERNS(ALT_STDOUT_DEV); +#endif +#ifdef ALT_STDERR_PRESENT + ALT_DRIVER_IOCTL_EXTERNS(ALT_STDERR_DEV); +#endif + +#if !defined(ALT_STDIN_PRESENT) && !defined(ALT_STDOUT_PRESENT) && !defined(ALT_STDERR_PRESENT) + /* Generate a link time warning, should this function ever be called. */ + ALT_STUB_WARNING(ioctl); +#endif + + switch (file) { +#ifdef ALT_STDIN_PRESENT + case 0: /* stdin file descriptor */ + return ALT_DRIVER_IOCTL(ALT_STDIN_DEV, req, arg); +#endif /* ALT_STDIN_PRESENT */ +#ifdef ALT_STDOUT_PRESENT + case 1: /* stdout file descriptor */ + return ALT_DRIVER_IOCTL(ALT_STDOUT_DEV, req, arg); +#endif /* ALT_STDOUT_PRESENT */ +#ifdef ALT_STDERR_PRESENT + case 2: /* stderr file descriptor */ + return ALT_DRIVER_IOCTL(ALT_STDERR_DEV, req, arg); +#endif /* ALT_STDERR_PRESENT */ + default: + ALT_ERRNO = EBADFD; + return -1; + } +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +int ALT_IOCTL (int file, int req, void* arg) +{ + alt_fd* fd; + int rc; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + + /* + * In the case of device drivers (not file systems) handle the TIOCEXCL + * and TIOCNXCL requests as special cases. + */ + + if (fd->fd_flags & ALT_FD_DEV) + { + if (req == TIOCEXCL) + { + rc = alt_fd_lock (fd); + goto ioctl_done; + } + else if (req == TIOCNXCL) + { + rc = alt_fd_unlock (fd); + goto ioctl_done; + } + } + + /* + * If the driver provides an ioctl() function, call that to handle the + * request, otherwise set the return code to indicate that the request + * could not be processed. + */ + + if (fd->dev->ioctl) + { + rc = fd->dev->ioctl(fd, req, arg); + } + else + { + rc = -ENOTTY; + } + } + else + { + rc = -EBADFD; + } + +ioctl_done: + + if (rc < 0) + { + ALT_ERRNO = -rc; + } + return rc; +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_irq_entry.S b/software/sys_controller_bsp/HAL/src/alt_irq_entry.S new file mode 100644 index 0000000..d3efe7d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_irq_entry.S @@ -0,0 +1,108 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "system.h" + +/* + * This is the interrupt exception entry point code, which saves all the + * registers and calls the interrupt handler. It should be pulled in using + * a .globl from alt_irq_register.c. This scheme is used so that if an + * interrupt is never registered, then this code will not appear in the + * generated executable, thereby improving code footprint. + */ + + /* + * Explicitly allow the use of r1 (the assembler temporary register) + * within this code. This register is normally reserved for the use of + * the compiler. + */ + .set noat + + /* + * Pull in the exception handler register save code. + */ + .globl alt_exception + + .globl alt_irq_entry + .section .exceptions.entry.label, "xa" +alt_irq_entry: + + /* + * Section .exceptions.entry is in alt_exception_entry.S + * This saves all the caller saved registers and reads estatus into r5 + */ + + .section .exceptions.irqtest, "xa" + +#ifdef ALT_CI_INTERRUPT_VECTOR_N + /* + * Use the interrupt vector custom instruction if present to accelerate + * this code. + * If the interrupt vector custom instruction returns a negative + * value, there are no interrupts active (estatus.pie is 0 + * or ipending is 0) so assume it is a software exception. + */ + custom ALT_CI_INTERRUPT_VECTOR_N, r4, r0, r0 + blt r4, r0, .Lnot_irq +#else + /* + * Test to see if the exception was a software exception or caused + * by an external interrupt, and vector accordingly. + */ + rdctl r4, ipending + andi r2, r5, 1 + beq r2, zero, .Lnot_irq + beq r4, zero, .Lnot_irq +#endif /* ALT_CI_INTERRUPT_VECTOR_N */ + + .section .exceptions.irqhandler, "xa" + /* + * Now that all necessary registers have been preserved, call + * alt_irq_handler() to process the interrupts. + */ + + call alt_irq_handler + + .section .exceptions.irqreturn, "xa" + + br .Lexception_exit + + .section .exceptions.notirq.label, "xa" + +.Lnot_irq: + + /* + * Section .exceptions.exit is in alt_exception_entry.S + * This restores all the caller saved registers + */ + + .section .exceptions.exit.label +.Lexception_exit: + diff --git a/software/sys_controller_bsp/HAL/src/alt_irq_handler.c b/software/sys_controller_bsp/HAL/src/alt_irq_handler.c new file mode 100644 index 0000000..3253d02 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_irq_handler.c @@ -0,0 +1,169 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include "system.h" + +/* + * This interrupt handler only works with an internal interrupt controller + * (IIC). Processors with an external interrupt controller (EIC) use an + * implementation provided by an EIC driver. + */ +#ifndef ALT_CPU_EIC_PRESENT + +#include "sys/alt_irq.h" +#include "os/alt_hooks.h" + +#include "alt_types.h" + +/* + * A table describing each interrupt handler. The index into the array is the + * interrupt id associated with the handler. + * + * When an interrupt occurs, the associated handler is called with + * the argument stored in the context member. + */ +struct ALT_IRQ_HANDLER +{ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + void (*handler)(void*); +#else + void (*handler)(void*, alt_u32); +#endif + void *context; +} alt_irq[ALT_NIRQ]; + +/* + * alt_irq_handler() is called by the interrupt exception handler in order to + * process any outstanding interrupts. + * + * It is defined here since it is linked in using weak linkage. + * This means that if there is never a call to alt_irq_register() (above) then + * this function will not get linked in to the executable. This is acceptable + * since if no handler is ever registered, then an interrupt can never occur. + * + * If Nios II interrupt vector custom instruction exists, use it to accelerate + * the dispatch of interrupt handlers. The Nios II interrupt vector custom + * instruction is present if the macro ALT_CI_INTERRUPT_VECTOR defined. + */ + +void alt_irq_handler (void) __attribute__ ((section (".exceptions"))); +void alt_irq_handler (void) +{ +#ifdef ALT_CI_INTERRUPT_VECTOR + alt_32 offset; + char* alt_irq_base = (char*)alt_irq; +#else + alt_u32 active; + alt_u32 mask; + alt_u32 i; +#endif /* ALT_CI_INTERRUPT_VECTOR */ + + /* + * Notify the operating system that we are at interrupt level. + */ + + ALT_OS_INT_ENTER(); + +#ifdef ALT_CI_INTERRUPT_VECTOR + /* + * Call the interrupt vector custom instruction using the + * ALT_CI_INTERRUPT_VECTOR macro. + * It returns the offset into the vector table of the lowest-valued pending + * interrupt (corresponds to highest priority) or a negative value if none. + * The custom instruction assumes that each table entry is eight bytes. + */ + while ((offset = ALT_CI_INTERRUPT_VECTOR) >= 0) { + struct ALT_IRQ_HANDLER* handler_entry = + (struct ALT_IRQ_HANDLER*)(alt_irq_base + offset); +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + handler_entry->handler(handler_entry->context); +#else + handler_entry->handler(handler_entry->context, offset >> 3); +#endif + } +#else /* ALT_CI_INTERRUPT_VECTOR */ + /* + * Obtain from the interrupt controller a bit list of pending interrupts, + * and then process the highest priority interrupt. This process loops, + * loading the active interrupt list on each pass until alt_irq_pending() + * return zero. + * + * The maximum interrupt latency for the highest priority interrupt is + * reduced by finding out which interrupts are pending as late as possible. + * Consider the case where the high priority interupt is asserted during + * the interrupt entry sequence for a lower priority interrupt to see why + * this is the case. + */ + + active = alt_irq_pending (); + + do + { + i = 0; + mask = 1; + + /* + * Test each bit in turn looking for an active interrupt. Once one is + * found, the interrupt handler asigned by a call to alt_irq_register() is + * called to clear the interrupt condition. + */ + + do + { + if (active & mask) + { +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + alt_irq[i].handler(alt_irq[i].context); +#else + alt_irq[i].handler(alt_irq[i].context, i); +#endif + break; + } + mask <<= 1; + i++; + + } while (1); + + active = alt_irq_pending (); + + } while (active); +#endif /* ALT_CI_INTERRUPT_VECTOR */ + + /* + * Notify the operating system that interrupt processing is complete. + */ + + ALT_OS_INT_EXIT(); +} + +#endif /* ALT_CPU_EIC_PRESENT */ diff --git a/software/sys_controller_bsp/HAL/src/alt_irq_register.c b/software/sys_controller_bsp/HAL/src/alt_irq_register.c new file mode 100644 index 0000000..b5ea474 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_irq_register.c @@ -0,0 +1,102 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ +#include +#include "system.h" + +/* + * This interrupt registry mechanism works with the Nios II internal interrupt + * controller (IIC) only. Systems with an external interrupt controller (EIC), + * or those with the IIC who are using the enhanced interrupt API will + * utilize the alt_ic_isr_register() routine to register an interrupt. + */ +#ifndef NIOS2_EIC_PRESENT + +#include "sys/alt_irq.h" +#include "priv/alt_legacy_irq.h" +#include "os/alt_hooks.h" + +#include "alt_types.h" + +/* + * The header, alt_irq_entry.h, contains the exception entry point, and is + * provided by the processor component. It is included here, so that the code + * will be added to the executable only if alt_irq_register() is present, i.e. + * if no interrupts are registered - there's no need to provide any + * interrupt handling. + */ + +#include "sys/alt_irq_entry.h" + +/* + * The header, alt_irq_table.h contains a table describing which function + * handles each interrupt. + */ + +#include "priv/alt_irq_table.h" + +/* + * alt_irq_handler() is called to register an interrupt handler. If the + * function is succesful, then the requested interrupt will be enabled upon + * return. Registering a NULL handler will disable the interrupt. + * + * The return value is 0 if the interrupt handler was registered and the + * interrupt was enabled, otherwise it is negative. + */ + +int alt_irq_register (alt_u32 id, + void* context, + alt_isr_func handler) +{ + int rc = -EINVAL; + alt_irq_context status; + + if (id < ALT_NIRQ) + { + /* + * interrupts are disabled while the handler tables are updated to ensure + * that an interrupt doesn't occur while the tables are in an inconsistant + * state. + */ + + status = alt_irq_disable_all (); + + alt_irq[id].handler = handler; + alt_irq[id].context = context; + + rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id); + + alt_irq_enable_all(status); + } + return rc; +} +#endif /* NIOS2_EIC_PRESENT */ + diff --git a/software/sys_controller_bsp/HAL/src/alt_irq_vars.c b/software/sys_controller_bsp/HAL/src/alt_irq_vars.c new file mode 100644 index 0000000..8c0a18d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_irq_vars.c @@ -0,0 +1,47 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "alt_types.h" + +#include "system.h" + +/* + * These global variables are used to save the current list of enabled + * interrupts. See alt_irq.h for further details. + */ + +volatile alt_u32 alt_irq_active = 0; + +#ifndef ALT_EXCEPTION_STACK + +volatile alt_u32 alt_priority_mask = (alt_u32) -1; + +#endif + diff --git a/software/sys_controller_bsp/HAL/src/alt_isatty.c b/software/sys_controller_bsp/HAL/src/alt_isatty.c new file mode 100644 index 0000000..9276472 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_isatty.c @@ -0,0 +1,125 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include "sys/alt_dev.h" +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +#ifdef ALT_USE_DIRECT_DRIVERS + +#include "system.h" + +/* + * Provide minimal version that just describes all file descriptors + * as tty devices for provided stdio devices. + */ +int ALT_ISATTY (int file) +{ + switch (file) { +#ifdef ALT_STDIN_PRESENT + case 0: /* stdin file descriptor */ +#endif /* ALT_STDIN_PRESENT */ +#ifdef ALT_STDOUT_PRESENT + case 1: /* stdout file descriptor */ +#endif /* ALT_STDOUT_PRESENT */ +#ifdef ALT_STDERR_PRESENT + case 2: /* stderr file descriptor */ +#endif /* ALT_STDERR_PRESENT */ + return 1; + default: + return 0; + } + +#if !defined(ALT_STDIN_PRESENT) && !defined(ALT_STDOUT_PRESENT) && !defined(ALT_STDERR_PRESENT) + /* Generate a link time warning, should this function ever be called. */ + ALT_STUB_WARNING(isatty); +#endif +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ +/* + * isatty() can be used to determine whether the input file descriptor "file" + * refers to a terminal device or not. If it is a terminal device then the + * return value is one, otherwise it is zero. + * + * ALT_ISATTY is mapped onto the isatty() system call in alt_syscall.h + */ + +int ALT_ISATTY (int file) +{ + alt_fd* fd; + struct stat stat; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + /* + * If a device driver does not provide an fstat() function, then it is + * treated as a terminal device by default. + */ + + if (!fd->dev->fstat) + { + return 1; + } + + /* + * If a driver does provide an implementation of the fstat() function, then + * this is called so that the device can identify itself. + */ + + else + { + fstat (file, &stat); + return (stat.st_mode == _IFCHR) ? 1 : 0; + } + } + else + { + ALT_ERRNO = EBADFD; + return 0; + } +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_kill.c b/software/sys_controller_bsp/HAL/src/alt_kill.c new file mode 100644 index 0000000..42c2e1d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_kill.c @@ -0,0 +1,121 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include "sys/alt_errno.h" +#include "os/alt_syscall.h" + + +/* + * kill() is used by newlib in order to send signals to processes. Since there + * is only a single process in the HAL, the only valid values for pid are + * either the current process id, or the broadcast values, i.e. pid must be + * less than or equal to zero. + * + * ALT_KILL is mapped onto the kill() system call in alt_syscall.h + */ + +int ALT_KILL (int pid, int sig) +{ + int status = 0; + + if (pid <= 0) + { + switch (sig) + { + case 0: + + /* The null signal is used to check that a pid is valid. */ + + break; + + case SIGABRT: + case SIGALRM: + case SIGFPE: + case SIGILL: + case SIGKILL: + case SIGPIPE: + case SIGQUIT: + case SIGSEGV: + case SIGTERM: + case SIGUSR1: + case SIGUSR2: + case SIGBUS: + case SIGPOLL: + case SIGPROF: + case SIGSYS: + case SIGTRAP: + case SIGVTALRM: + case SIGXCPU: + case SIGXFSZ: + + /* + * The Posix standard defines the default behaviour for all these signals + * as being eqivalent to a call to _exit(). No mechanism is provided to + * change this behaviour. + */ + + _exit(0); + case SIGCHLD: + case SIGURG: + + /* + * The Posix standard defines these signals to be ignored by default. No + * mechanism is provided to change this behaviour. + */ + + break; + default: + + /* Tried to send an unsupported signal */ + + status = EINVAL; + } + } + + else if (pid > 0) + { + /* Attempted to signal a non-existant process */ + + status = ESRCH; + } + + if (status) + { + ALT_ERRNO = status; + return -1; + } + + return 0; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_link.c b/software/sys_controller_bsp/HAL/src/alt_link.c new file mode 100644 index 0000000..d796c59 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_link.c @@ -0,0 +1,56 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_warning.h" +#include "sys/alt_errno.h" +#include "os/alt_syscall.h" + +/* + * link() is used by newlib to create a new link to an existing file. This is + * unsupported in the HAL environment. However a "do-nothing" implementation + * is still provied for newlib compatability. + * + * ALT_LINK is mapped onto the link() system call in alt_syscall.h + */ + +int ALT_LINK ( char *existing, char *new) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(link); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_load.c b/software/sys_controller_bsp/HAL/src/alt_load.c new file mode 100644 index 0000000..644fdb4 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_load.c @@ -0,0 +1,88 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_load.h" +#include "sys/alt_cache.h" + +/* + * Linker defined symbols. + */ + +extern alt_u32 __flash_rwdata_start; +extern alt_u32 __ram_rwdata_start; +extern alt_u32 __ram_rwdata_end; +extern alt_u32 __flash_rodata_start; +extern alt_u32 __ram_rodata_start; +extern alt_u32 __ram_rodata_end; +extern alt_u32 __flash_exceptions_start; +extern alt_u32 __ram_exceptions_start; +extern alt_u32 __ram_exceptions_end; + +/* + * alt_load() is called when the code is executing from flash. In this case + * there is no bootloader, so this application is responsible for loading to + * RAM any sections that are required. + */ + +void alt_load (void) +{ + /* + * Copy the .rwdata section. + */ + + alt_load_section (&__flash_rwdata_start, + &__ram_rwdata_start, + &__ram_rwdata_end); + + /* + * Copy the exception handler. + */ + + alt_load_section (&__flash_exceptions_start, + &__ram_exceptions_start, + &__ram_exceptions_end); + + /* + * Copy the .rodata section. + */ + + alt_load_section (&__flash_rodata_start, + &__ram_rodata_start, + &__ram_rodata_end); + + /* + * Now ensure that the caches are in synch. + */ + + alt_dcache_flush_all(); + alt_icache_flush_all(); +} diff --git a/software/sys_controller_bsp/HAL/src/alt_log_macro.S b/software/sys_controller_bsp/HAL/src/alt_log_macro.S new file mode 100644 index 0000000..23e3019 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_log_macro.S @@ -0,0 +1,60 @@ +/* alt_log_macro.S + * + * Implements the function tx_log_str, called by the assembly macro + * ALT_LOG_PUTS(). The macro will be empty when logging is turned off, + * and this function will not be compiled. When logging is on, + * this function is used to print out the strings defined in the beginning + * of alt_log_printf.c, using port information taken from system.h and + * alt_log_printf.h. + * + * This routine only handles strings, and sends a character into the defined + * output device's output buffer when the device is ready. It's intended for + * debugging purposes, where messages can be set to print out at certain + * points in the boot code to indicate the progress of the program. + * + */ + +#ifndef __ALT_LOG_MACROS__ +#define __ALT_LOG_MACROS__ + +/* define this flag to skip assembly-incompatible parts + * of various include files. */ +#define ALT_ASM_SRC + +#ifdef ALT_LOG_ENABLE // only compile this function if this flag is defined. + + #include "system.h" + #include "sys/alt_log_printf.h" + + .global tx_log_str +tx_log_str: + /* load base uart / jtag uart address into r6 */ + movhi r6, %hiadj(ALT_LOG_PORT_BASE) + addi r6, r6, %lo(ALT_LOG_PORT_BASE) +tx_next_char: + /* if pointer points to null, return + * r4 is the pointer to the str to be printed, set by ALT_LOG_PUTS */ + ldb r7, (r4) + beq r0, r7, end_tx + + /* check device transmit ready */ +wait_tx_ready_loop: + ldwio r8, ALT_LOG_PRINT_REG_OFFSET(r6) + /*UART, ALT_LOG_PRINT_MSK == 0x40 + JTAG UART, ALT_LOG_PRINT_MSK == 0xFFFF0000 */ + andhi r5, r8, %hi(ALT_LOG_PRINT_MSK) + andi r8, r8, %lo(ALT_LOG_PRINT_MSK) + or r5, r5, r8 + beq r5, r0, wait_tx_ready_loop + /* write char */ + stwio r7, ALT_LOG_PRINT_TXDATA_REG_OFFSET (r6) + /* advance string pointer */ + addi r4, r4, 1 + br tx_next_char +end_tx: + ret + +#endif + +#endif /* __ALT_LOG_MACROS__ */ + diff --git a/software/sys_controller_bsp/HAL/src/alt_log_printf.c b/software/sys_controller_bsp/HAL/src/alt_log_printf.c new file mode 100644 index 0000000..1f7056d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_log_printf.c @@ -0,0 +1,479 @@ + +/* alt_log_printf.c + * + * This file implements the various C functions used for the + * alt_log logging/debugging print functions. The functions + * sit as is here - the job of hiding them from the compiler + * if logging is disabled is accomplished in the .h file. + * + * All the global variables for alt_log are defined here. + * These include the various flags that turn on additional + * logging options; the strings for assembly printing; and + * other globals needed by different logging options. + * + * There are 4 functions that handle the actual printing: + * alt_log_txchar: Actual function that puts 1 char to UART/JTAG UART. + * alt_log_repchar: Calls alt_log_txchar 'n' times - used by + * alt_log_private_printf for formatting. + * alt_log_private_printf: + * Stripped down implementation of printf - no floats. + * alt_log_printf_proc: + * Wrapper function for private_printf. + * + * The rest of the functions are called by the macros which + * were called by code in the other components. Each function + * is preceded by a comment, about which file it gets called + * in, and what its purpose is. + * + * author: gkwan + */ + +/* skip all code if enable is off */ +#ifdef ALT_LOG_ENABLE + +#include +#include +#include +#ifdef __ALTERA_AVALON_JTAG_UART + #include "altera_avalon_jtag_uart.h" + #include +#endif +#include "sys/alt_log_printf.h" + +/* strings for assembly puts */ +char alt_log_msg_bss[] = "[crt0.S] Clearing BSS \r\n";; +char alt_log_msg_alt_main[] = "[crt0.S] Calling alt_main.\r\n"; +char alt_log_msg_stackpointer[] \ + = "[crt0.S] Setting up stack and global pointers.\r\n"; +char alt_log_msg_cache[] = "[crt0.S] Inst & Data Cache Initialized.\r\n"; +/* char array allocation for alt_write */ +char alt_log_write_buf[ALT_LOG_WRITE_ECHO_LEN+2]; + +/* global variables for all 'on' flags */ + +/* + * The boot message flag is linked into the data (rwdata) section + * because if it is zero, it would otherwise be placed in the bss section. + * alt_log examines this variable before the BSS is cleared in the boot-up + * process. + */ +volatile alt_u32 alt_log_boot_on_flag \ + __attribute__ ((section (".data"))) = ALT_LOG_BOOT_ON_FLAG_SETTING; + +volatile alt_u8 alt_log_write_on_flag = ALT_LOG_WRITE_ON_FLAG_SETTING; + +volatile alt_u8 alt_log_sys_clk_on_flag = ALT_LOG_SYS_CLK_ON_FLAG_SETTING; + +volatile alt_u8 alt_log_jtag_uart_alarm_on_flag = \ + ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING; + +volatile alt_u8 alt_log_jtag_uart_isr_on_flag = \ + ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING; + +volatile alt_u8 alt_log_jtag_uart_startup_info_on_flag = \ + ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING; + +/* Global alarm object for recurrent JTAG UART status printing */ +alt_alarm alt_log_jtag_uart_alarm_1; + +/* Global ints for system clock printing and count */ +volatile int alt_log_sys_clk_count; +volatile int alt_system_clock_in_sec; + +/* enum used by alt_log_private_printf */ +enum +{ + pfState_chars, + pfState_firstFmtChar, + pfState_otherFmtChar +}; + + + + +/* Function to put one char onto the UART/JTAG UART txdata register. */ +void alt_log_txchar(int c,char *base) +{ + /* Wait until the device is ready for a character */ + while((ALT_LOG_PRINT_REG_RD(base) & ALT_LOG_PRINT_MSK) == 0) + ; + /* And pop the character into the register */ + ALT_LOG_PRINT_TXDATA_WR(base,c); +} + + +/* Called by alt_log_private_printf to print out characters repeatedly */ +void alt_log_repchar(char c,int r,int base) +{ + while(r-- > 0) + alt_log_txchar(c,(char*) base); +} + + +/* Stripped down printf function */ +void alt_log_private_printf(const char *fmt,int base,va_list args) + { + const char *w; + char c; + int state; + int fmtLeadingZero = 0; /* init these all to 0 for -W warnings. */ + int fmtLong = 0; + int fmtBeforeDecimal = 0; + int fmtAfterDecimal = 0; + int fmtBase = 0; + int fmtSigned = 0; + int fmtCase = 0; /* For hex format, if 1, A-F, else a-f. */ + + w = fmt; + state = pfState_chars; + + while(0 != (c = *w++)) + { + switch(state) + { + case pfState_chars: + if(c == '%') + { + fmtLeadingZero = 0; + fmtLong = 0; + fmtBase = 10; + fmtSigned = 1; + fmtCase = 0; /* Only %X sets this. */ + fmtBeforeDecimal = -1; + fmtAfterDecimal = -1; + state = pfState_firstFmtChar; + } + else + { + alt_log_txchar(c,(char*)base); + } + break; + + case pfState_firstFmtChar: + if(c == '0') + { + fmtLeadingZero = 1; + state = pfState_otherFmtChar; + } + else if(c == '%') + { + alt_log_txchar(c,(char*)base); + state = pfState_chars; + } + else + { + state = pfState_otherFmtChar; + goto otherFmtChar; + } + break; + + case pfState_otherFmtChar: +otherFmtChar: + if(c == '.') + { + fmtAfterDecimal = 0; + } + else if('0' <= c && c <= '9') + { + c -= '0'; + if(fmtAfterDecimal < 0) /* still before decimal */ + { + if(fmtBeforeDecimal < 0) + { + fmtBeforeDecimal = 0; + } + else + { + fmtBeforeDecimal *= 10; + } + fmtBeforeDecimal += c; + } + else + { + fmtAfterDecimal = (fmtAfterDecimal * 10) + c; + } + } + else if(c == 'l') + { + fmtLong = 1; + } + else /* we're up to the letter which determines type */ + { + switch(c) + { + case 'd': + case 'i': +doIntegerPrint: + { + unsigned long v; + unsigned long p; /* biggest power of fmtBase */ + unsigned long vShrink; /* used to count digits */ + int sign; + int digitCount; + + /* Get the value */ + if(fmtLong) + { + if (fmtSigned) + { + v = va_arg(args,long); + } + else + { + v = va_arg(args,unsigned long); + } + } + else + { + if (fmtSigned) + { + v = va_arg(args,int); + } + else + { + v = va_arg(args,unsigned int); + } + } + + /* Strip sign */ + sign = 0; + /* (assumes sign bit is #31) */ + if( fmtSigned && (v & (0x80000000)) ) + { + v = ~v + 1; + sign = 1; + } + + /* Count digits, and get largest place value */ + vShrink = v; + p = 1; + digitCount = 1; + while( (vShrink = vShrink / fmtBase) > 0 ) + { + digitCount++; + p *= fmtBase; + } + + /* Print leading characters & sign */ + fmtBeforeDecimal -= digitCount; + if(fmtLeadingZero) + { + if(sign) + { + alt_log_txchar('-',(char*)base); + fmtBeforeDecimal--; + } + alt_log_repchar('0',fmtBeforeDecimal,base); + } + else + { + if(sign) + { + fmtBeforeDecimal--; + } + alt_log_repchar(' ',fmtBeforeDecimal,base); + if(sign) + { + alt_log_txchar('-',(char*)base); + } + } + + /* Print numbery parts */ + while(p) + { + unsigned char d; + + d = v / p; + d += '0'; + if(d > '9') + { + d += (fmtCase ? 'A' : 'a') - '0' - 10; + } + alt_log_txchar(d,(char*)base); + + v = v % p; + p = p / fmtBase; + } + } + + state = pfState_chars; + break; + + case 'u': + fmtSigned = 0; + goto doIntegerPrint; + case 'o': + fmtSigned = 0; + fmtBase = 8; + goto doIntegerPrint; + case 'x': + fmtSigned = 0; + fmtBase = 16; + goto doIntegerPrint; + case 'X': + fmtSigned = 0; + fmtBase = 16; + fmtCase = 1; + goto doIntegerPrint; + + case 'c': + alt_log_repchar(' ',fmtBeforeDecimal-1,base); + alt_log_txchar(va_arg(args,int),(char*)base); + break; + + case 's': + { + char *s; + + s = va_arg(args,char *); + alt_log_repchar(' ',fmtBeforeDecimal-strlen(s),base); + + while(*s) + alt_log_txchar(*s++,(char*)base); + } + break; + } /* switch last letter of fmt */ + state=pfState_chars; + } + break; + } /* switch */ + } /* while chars left */ + } /* printf */ + +/* Main logging printf function */ +int alt_log_printf_proc(const char *fmt, ... ) +{ + va_list args; + + va_start (args, fmt); + alt_log_private_printf(fmt,ALT_LOG_PORT_BASE,args); + return (0); +} + +/* Below are the functions called by different macros in various components. */ + +/* If the system has a JTAG_UART, include JTAG_UART debugging functions */ +#ifdef __ALTERA_AVALON_JTAG_UART + +/* The alarm function in altera_avalon_jtag_uart.c. + * This function, when turned on, prints out the status + * of the JTAG UART Control register, every ALT_LOG_JTAG_UART_TICKS. + * If the flag is off, the alarm should never be registered, and this + * function should never run */ +alt_u32 altera_avalon_jtag_uart_report_log(void * context) +{ + if (alt_log_jtag_uart_alarm_on_flag) { + altera_avalon_jtag_uart_state* dev = (altera_avalon_jtag_uart_state*) context; + const char* header="JTAG Alarm:"; + alt_log_jtag_uart_print_control_reg(dev, dev->base, header); + return ALT_LOG_JTAG_UART_TICKS; + } + else + { + /* If flag is not on, return 0 to disable future alarms. + * Should never be here, alarm should not be enabled at all. */ + return 0; + } +} + +void alt_log_jtag_uart_print_control_reg(altera_avalon_jtag_uart_state* dev, int base, const char* header) +{ + unsigned int control, space, ac, wi, ri, we, re; + control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base); + space = (control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK) >> + ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST; + we= (control & ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK) >> + ALTERA_AVALON_JTAG_UART_CONTROL_WE_OFST; + re= (control & ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK) >> + ALTERA_AVALON_JTAG_UART_CONTROL_RE_OFST; + ri= (control & ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK) >> + ALTERA_AVALON_JTAG_UART_CONTROL_RI_OFST; + wi= (control & ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK) >> + ALTERA_AVALON_JTAG_UART_CONTROL_WI_OFST; + ac= (control & ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK) >> + ALTERA_AVALON_JTAG_UART_CONTROL_AC_OFST; + +#ifdef ALTERA_AVALON_JTAG_UART_SMALL + ALT_LOG_PRINTF( + "%s HW FIFO wspace=%d AC=%d WI=%d RI=%d WE=%d RE=%d\r\n", + header,space,ac,wi,ri,we,re); +#else + ALT_LOG_PRINTF( + "%s SW CirBuf = %d, HW FIFO wspace=%d AC=%d WI=%d RI=%d WE=%d RE=%d\r\n", + header,(dev->tx_out-dev->tx_in),space,ac,wi,ri,we,re); +#endif + + return; + +} + +/* In altera_avalon_jtag_uart.c + * Same output as the alarm function above, but this is called in the driver + * init function. Hence, it gives the status of the JTAG UART control register + * right at the initialization of the driver */ +void alt_log_jtag_uart_startup_info(altera_avalon_jtag_uart_state* dev, int base) +{ + const char* header="JTAG Startup Info:"; + alt_log_jtag_uart_print_control_reg(dev, base, header); + return; +} + +/* In altera_avalon_jtag_uart.c + * When turned on, this function will print out the status of the jtag uart + * control register every time there is a jtag uart "almost-empty" interrupt. */ +void alt_log_jtag_uart_isr_proc(int base, altera_avalon_jtag_uart_state* dev) +{ + if (alt_log_jtag_uart_isr_on_flag) { + const char* header="JTAG IRQ:"; + alt_log_jtag_uart_print_control_reg(dev, base, header); + } + return; +} + +#endif /* __ALTERA_AVALON_JTAG_UART */ + +/* In alt_write.c + * When the alt_log_write_on_flag is turned on, this function gets called + * every time alt_write gets called. The first + * ALT_LOG_WRITE_ECHO_LEN characters of every printf command (or any command + * that eventually calls write()) gets echoed to the alt_log output. */ +void alt_log_write(const void *ptr, size_t len) +{ + if (alt_log_write_on_flag) { + int temp_cnt; + int length=(ALT_LOG_WRITE_ECHO_LEN>len) ? len : ALT_LOG_WRITE_ECHO_LEN; + + if (length < 2) return; + + strncpy (alt_log_write_buf,ptr,length); + alt_log_write_buf[length-1]='\n'; + alt_log_write_buf[length]='\r'; + alt_log_write_buf[length+1]='\0'; + + /* Escape Ctrl-D's. If the Ctrl-D gets sent it might kill the terminal + * connection of alt_log. It will get replaced by 'D'. */ + for (temp_cnt=0;temp_cnt < length; temp_cnt++) { + if (alt_log_write_buf[temp_cnt]== 0x4) { + alt_log_write_buf[temp_cnt]='D'; + } + } + ALT_LOG_PRINTF("Write Echo: %s",alt_log_write_buf); + } +} + +/* In altera_avalon_timer_sc + * This function prints out a system clock is alive message + * every ALT_LOG_SYS_CLK_INTERVAL (in ticks). */ +void alt_log_system_clock() +{ + if (alt_log_sys_clk_on_flag) { + alt_log_sys_clk_count++; + if (alt_log_sys_clk_count > ALT_LOG_SYS_CLK_INTERVAL) { + alt_log_sys_clk_count = 0; + ALT_LOG_PRINTF("System Clock On %u\r\n",alt_system_clock_in_sec++); + } + } +} + + +#endif diff --git a/software/sys_controller_bsp/HAL/src/alt_lseek.c b/software/sys_controller_bsp/HAL/src/alt_lseek.c new file mode 100644 index 0000000..7857b0d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_lseek.c @@ -0,0 +1,117 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +#ifdef ALT_USE_DIRECT_DRIVERS + +off_t ALT_LSEEK (int file, off_t ptr, int dir) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(lseek); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +/* + * lseek() can be called to move the read/write pointer associated with the + * file descriptor "file". This function simply vectors the call to the lseek() + * function provided by the driver associated with the file descriptor. + * + * If the driver does not provide an implementation of lseek() an error is + * indicated. + * + * lseek() corresponds to the standard lseek() function. + * + * ALT_LSEEK is mapped onto the lseek() system call in alt_syscall.h + * + */ + +off_t ALT_LSEEK (int file, off_t ptr, int dir) +{ + alt_fd* fd; + off_t rc = 0; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + /* + * If the device driver provides an implementation of the lseek() function, + * then call that to process the request. + */ + + if (fd->dev->lseek) + { + rc = fd->dev->lseek(fd, ptr, dir); + } + /* + * Otherwise return an error. + */ + + else + { + rc = -ENOTSUP; + } + } + else + { + rc = -EBADFD; + } + + if (rc < 0) + { + ALT_ERRNO = -rc; + rc = -1; + } + + return rc; +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_main.c b/software/sys_controller_bsp/HAL/src/alt_main.c new file mode 100644 index 0000000..a96229b --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_main.c @@ -0,0 +1,161 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "sys/alt_dev.h" +#include "sys/alt_sys_init.h" +#include "sys/alt_irq.h" +#include "sys/alt_dev.h" + +#include "os/alt_hooks.h" + +#include "priv/alt_file.h" +#include "alt_types.h" + +#include "system.h" + +#include "sys/alt_log_printf.h" + +extern void _do_ctors(void); +extern void _do_dtors(void); + +/* + * Standard arguments for main. By default, no arguments are passed to main. + * However a device driver may choose to configure these arguments by calling + * alt_set_args(). The expectation is that this facility will only be used by + * the iclient/ihost utility. + */ + +int alt_argc = 0; +char** alt_argv = {NULL}; +char** alt_envp = {NULL}; + +/* + * Prototype for the entry point to the users application. + */ + +extern int main (int, char **, char **); + +/* + * alt_main is the C entry point for the HAL. It is called by the assembler + * startup code in the processor specific crt0.S. It is responsible for: + * completing the C runtime configuration; configuring all the + * devices/filesystems/components in the system; and call the entry point for + * the users application, i.e. main(). + */ + +void alt_main (void) +{ +#ifndef ALT_NO_EXIT + int result; +#endif + + /* ALT LOG - please see HAL/sys/alt_log_printf.h for details */ + ALT_LOG_PRINT_BOOT("[alt_main.c] Entering alt_main, calling alt_irq_init.\r\n"); + /* Initialize the interrupt controller. */ + alt_irq_init (NULL); + + /* Initialize the operating system */ + ALT_LOG_PRINT_BOOT("[alt_main.c] Done alt_irq_init, calling alt_os_init.\r\n"); + ALT_OS_INIT(); + + /* + * Initialize the semaphore used to control access to the file descriptor + * list. + */ + + ALT_LOG_PRINT_BOOT("[alt_main.c] Done OS Init, calling alt_sem_create.\r\n"); + ALT_SEM_CREATE (&alt_fd_list_lock, 1); + + /* Initialize the device drivers/software components. */ + ALT_LOG_PRINT_BOOT("[alt_main.c] Calling alt_sys_init.\r\n"); + alt_sys_init(); + ALT_LOG_PRINT_BOOT("[alt_main.c] Done alt_sys_init.\r\n"); + +#if !defined(ALT_USE_DIRECT_DRIVERS) && (defined(ALT_STDIN_PRESENT) || defined(ALT_STDOUT_PRESENT) || defined(ALT_STDERR_PRESENT)) + + /* + * Redirect stdio to the apropriate devices now that the devices have + * been initialized. This is only done if the user has requested these + * devices be present (not equal to /dev/null) and if direct drivers + * aren't being used. + */ + + ALT_LOG_PRINT_BOOT("[alt_main.c] Redirecting IO.\r\n"); + alt_io_redirect(ALT_STDOUT, ALT_STDIN, ALT_STDERR); +#endif + +#ifndef ALT_NO_C_PLUS_PLUS + /* + * Call the C++ constructors + */ + + ALT_LOG_PRINT_BOOT("[alt_main.c] Calling C++ constructors.\r\n"); + _do_ctors (); +#endif /* ALT_NO_C_PLUS_PLUS */ + +#if !defined(ALT_NO_C_PLUS_PLUS) && !defined(ALT_NO_CLEAN_EXIT) && !defined(ALT_NO_EXIT) + /* + * Set the C++ destructors to be called at system shutdown. This is only done + * if a clean exit has been requested (i.e. the exit() function has not been + * redefined as _exit()). This is in the interest of reducing code footprint, + * in that the atexit() overhead is removed when it's not needed. + */ + + ALT_LOG_PRINT_BOOT("[alt_main.c] Calling atexit.\r\n"); + atexit (_do_dtors); +#endif + + /* + * Finally, call main(). The return code is then passed to a subsequent + * call to exit() unless the application is never supposed to exit. + */ + + ALT_LOG_PRINT_BOOT("[alt_main.c] Calling main.\r\n"); + +#ifdef ALT_NO_EXIT + main (alt_argc, alt_argv, alt_envp); +#else + result = main (alt_argc, alt_argv, alt_envp); + close(STDOUT_FILENO); + exit (result); +#endif + + ALT_LOG_PRINT_BOOT("[alt_main.c] After main - we should not be here?.\r\n"); +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_malloc_lock.c b/software/sys_controller_bsp/HAL/src/alt_malloc_lock.c new file mode 100644 index 0000000..8c78f46 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_malloc_lock.c @@ -0,0 +1,52 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +/* + * These are the empty malloc lock/unlock stubs required by newlib. These are + * used to make newlib's malloc() function thread safe. The default HAL + * configuration is single threaded, so there is nothing to do here. Note that + * this requires that malloc is never called by an interrupt service routine. + */ + +void __malloc_lock ( struct _reent *_r ) +{ +} + +/* + * + */ + +void __malloc_unlock ( struct _reent *_r ) +{ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_mcount.S b/software/sys_controller_bsp/HAL/src/alt_mcount.S new file mode 100644 index 0000000..3837523 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_mcount.S @@ -0,0 +1,198 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2010 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +/* mcount or _mcount is inserted by GCC before the function prologue of every + * function when a program is compiled for profiling. At the start of mcount, + * we guarantee that: + * ra = self_pc (an address in the function which called mcount) + * r8 = from_pc (an address in the function which called mcount's caller) + * + * Because this is always called at the start of a function we can corrupt + * r2,r3 and r11-r15. We must not corrupt r4-r7 (because they might contain + * function arguments for the instrumented function) or r8 (which holds ra + * for the instrumented function). + */ + + .global __mcount_fn_head + + .global mcount + + /* _mcount is used by gcc4 */ + .global _mcount + +_mcount: +mcount: + /* Use a hash to speed up locating fn_entry. We use bits 5 upwards to choose + * the bucket because bits 1:0 will always be 0, and because the distribution + * of values for bits 4:2 won't be even (aligning on cache line boundaries + * will skew it). Higher bits should be fairly random. + */ + /* fn_head = mcount_fn_head + (((unsigned int)self_pc >> 5) & (HASH_BUCKETS - 1)); */ + + srli r2, ra, 3 + movhi r3, %hiadj(__mcount_fn_head) + addi r3, r3, %lo(__mcount_fn_head) + andi r2, r2, 0xFC + add r11, r2, r3 + + /* The fast case is where we have already allocated a function arc, and so + * also a function pointer. + */ + + /* First find the function being called (using self_pc) */ + mov r10, r11 +0: + ldw r10, 0(r10) + beq r10, zero, .Lnew_arc + ldw r2, 4(r10) + bne r2, ra, 0b + + /* Found a function entry for this PC. Now look for an arc with a matching + * from_pc value. There will always be at least one arc. */ + ldw r3, 8(r10) +0: + ldw r2, 4(r3) + beq r2, r8, .Lfound_arc + ldw r3, 0(r3) + bne r3, zero, 0b + +.Lnew_arc: + addi sp, sp, -24 + +.LCFI0: + stw ra, 0(sp) + stw r4, 4(sp) + stw r5, 8(sp) + stw r6, 12(sp) + stw r7, 16(sp) + stw r8, 20(sp) + +.LCFI1: + /* __mcount_record(orig_ra, orig_r8, fn_entry, *fn_head); */ + mov r4, ra + mov r5, r8 + mov r6, r10 + mov r7, r11 + call __mcount_record + + /* restore registers from the stack */ + ldw ra, 0(sp) + ldw r4, 4(sp) + ldw r5, 8(sp) + ldw r6, 12(sp) + ldw r7, 16(sp) + ldw r8, 20(sp) + + addi sp, sp, 24 + +.LCFI2: + ret + +.Lfound_arc: + /* We've found the correct arc record. Increment the count and return */ + ldw r2, 8(r3) + addi r2, r2, 1 + stw r2, 8(r3) + ret + +.Lmcount_end: + + + +/* + * Dwarf2 debug information for the function. This provides GDB with the + * information it needs to backtrace out of this function. + */ + + .section .debug_frame,"",@progbits +.LCIE: + .4byte 2f - 1f /* Length */ +1: + .4byte 0xffffffff /* CIE id */ + .byte 0x1 /* Version */ + .string "" /* Augmentation */ + .uleb128 0x1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 0x1f /* Return address register */ + + .byte 0xc /* Define CFA */ + .uleb128 0x1b /* Register 27 (sp) */ + .uleb128 0x0 /* Offset 0 */ + + .align 2 /* Padding */ +2: + +.LFDE_mcount: + .4byte 2f - 1f /* Length */ +1: + .4byte .LCIE /* Pointer to CIE */ + .4byte mcount /* Start of table entry */ + .4byte .Lmcount_end - mcount /* Size of table entry */ + + .byte 0x4 /* Advance location */ + .4byte .LCFI0 - mcount /* to .LCFI0 */ + .byte 0xe /* Define CFA offset */ + .uleb128 24 /* to 24 */ + + .byte 0x4 /* Advance location */ + .4byte .LCFI1 - .LCFI0 /* to .LCFI1 */ + .byte 0x9f /* Store ra */ + .uleb128 0x6 /* at CFA-24 */ + .byte 0x84 /* Store r4 */ + .uleb128 0x5 /* at CFA-20 */ + .byte 0x85 /* Store r5 */ + .uleb128 0x4 /* at CFA-16 */ + .byte 0x86 /* Store r6 */ + .uleb128 0x3 /* at CFA-12 */ + .byte 0x87 /* Store r7 */ + .uleb128 0x2 /* at CFA-8 */ + .byte 0x88 /* Store r8 */ + .uleb128 0x1 /* at CFA-4 */ + + .byte 0x4 /* Advance location */ + .4byte .LCFI2 - .LCFI1 /* to .LCFI2 */ + .byte 0xe /* Define CFA offset */ + .uleb128 0 /* to 0 */ + .byte 0x8 /* Same value */ + .uleb128 31 /* for ra */ + .byte 0x8 /* Same value */ + .uleb128 4 /* for r4 */ + .byte 0x8 /* Same value */ + .uleb128 5 /* for r5 */ + .byte 0x8 /* Same value */ + .uleb128 6 /* for r6 */ + .byte 0x8 /* Same value */ + .uleb128 7 /* for r7 */ + .byte 0x8 /* Same value */ + .uleb128 8 /* for r8 */ + + .align 2 +2: + diff --git a/software/sys_controller_bsp/HAL/src/alt_open.c b/software/sys_controller_bsp/HAL/src/alt_open.c new file mode 100644 index 0000000..4790f53 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_open.c @@ -0,0 +1,173 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "alt_types.h" +#include "os/alt_syscall.h" + +#ifdef ALT_USE_DIRECT_DRIVERS + +int ALT_OPEN (const char* file, int flags, int mode) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(open); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +extern alt_llist alt_dev_list; + +/* + * alt_file_locked() is used by open() to ensure that a device has not been + * previously locked for exclusive access using ioctl(). This test is only + * performed for devices. Filesystems are required to handle the ioctl() call + * themselves, and report the error from the filesystems open() function. + */ + +static int alt_file_locked (alt_fd* fd) +{ + alt_u32 i; + + /* + * Mark the file descriptor as belonging to a device. + */ + + fd->fd_flags |= ALT_FD_DEV; + + /* + * Loop through all current file descriptors searching for one that's locked + * for exclusive access. If a match is found, generate an error. + */ + + for (i = 0; i <= alt_max_fd; i++) + { + if ((alt_fd_list[i].dev == fd->dev) && + (alt_fd_list[i].fd_flags & ALT_FD_EXCL) && + (&alt_fd_list[i] != fd)) + { + return -EACCES; + } + } + + /* The device is not locked */ + + return 0; +} + +/* + * open() is called in order to get a file descriptor that reference the file + * or device named "name". This descriptor can then be used to manipulate the + * file/device using the standard system calls, e.g. write(), read(), ioctl() + * etc. + * + * This is equivalent to the standard open() system call. + * + * ALT_OPEN is mapped onto the open() system call in alt_syscall.h + */ + +int ALT_OPEN (const char* file, int flags, int mode) +{ + alt_dev* dev; + alt_fd* fd; + int index = -1; + int status = -ENODEV; + int isafs = 0; + + /* + * Check the device list, to see if a device with a matching name is + * registered. + */ + + if (!(dev = alt_find_dev (file, &alt_dev_list))) + { + /* No matching device, so try the filesystem list */ + + dev = alt_find_file (file); + isafs = 1; + } + + /* + * If a matching device or filesystem is found, allocate a file descriptor. + */ + + if (dev) + { + if ((index = alt_get_fd (dev)) < 0) + { + status = index; + } + else + { + fd = &alt_fd_list[index]; + fd->fd_flags = (flags & ~ALT_FD_FLAGS_MASK); + + /* If this is a device, ensure it isn't already locked */ + + if (isafs || ((status = alt_file_locked (fd)) >= 0)) + { + /* + * If the device or filesystem provides an open() callback function, + * call it now to perform any device/filesystem specific operations. + */ + + status = (dev->open) ? dev->open(fd, file, flags, mode): 0; + } + } + } + else + { + status = -ENODEV; + } + + /* Allocation failed, so clean up and return an error */ + + if (status < 0) + { + alt_release_fd (index); + ALT_ERRNO = -status; + return -1; + } + + /* return the reference upon success */ + + return index; +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_printf.c b/software/sys_controller_bsp/HAL/src/alt_printf.c new file mode 100644 index 0000000..7789934 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_printf.c @@ -0,0 +1,132 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +/* + * This file provides a very minimal printf implementation for use with very + * small applications. Only the following format strings are supported: + * %x + * %s + * %c + * %% + */ + +#include +#include "sys/alt_stdio.h" +#ifdef ALT_SEMIHOSTING +#define alt_putchar(x) alt_putcharbuf(x) +#endif +/* + * ALT printf function + */ +void +alt_printf(const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + const char *w; + char c; + + /* Process format string. */ + w = fmt; + while ((c = *w++) != 0) + { + /* If not a format escape character, just print */ + /* character. Otherwise, process format string. */ + if (c != '%') + { + alt_putchar(c); + } + else + { + /* Get format character. If none */ + /* available, processing is complete. */ + if ((c = *w++) != 0) + { + if (c == '%') + { + /* Process "%" escape sequence. */ + alt_putchar(c); + } + else if (c == 'c') + { + int v = va_arg(args, int); + alt_putchar(v); + } + else if (c == 'x') + { + /* Process hexadecimal number format. */ + unsigned long v = va_arg(args, unsigned long); + unsigned long digit; + int digit_shift; + + /* If the number value is zero, just print and continue. */ + if (v == 0) + { + alt_putchar('0'); + continue; + } + + /* Find first non-zero digit. */ + digit_shift = 28; + while (!(v & (0xF << digit_shift))) + digit_shift -= 4; + + /* Print digits. */ + for (; digit_shift >= 0; digit_shift -= 4) + { + digit = (v & (0xF << digit_shift)) >> digit_shift; + if (digit <= 9) + c = '0' + digit; + else + c = 'a' + digit - 10; + alt_putchar(c); + } + } + else if (c == 's') + { + /* Process string format. */ + char *s = va_arg(args, char *); + + while(*s) + alt_putchar(*s++); + } + } + else + { + break; + } + } + } +#ifdef ALT_SEMIHOSTING + alt_putbufflush(); +#endif +} diff --git a/software/sys_controller_bsp/HAL/src/alt_putchar.c b/software/sys_controller_bsp/HAL/src/alt_putchar.c new file mode 100644 index 0000000..10bce1b --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_putchar.c @@ -0,0 +1,68 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#ifdef ALT_USE_DIRECT_DRIVERS +#include "system.h" +#include "sys/alt_driver.h" +#include "sys/alt_stdio.h" +#endif +#ifdef ALT_SEMIHOSTING +#include "sys/alt_stdio.h" +#include "unistd.h" +#endif + +/* + * Uses the ALT_DRIVER_WRITE() macro to call directly to driver if available. + * Otherwise, uses newlib provided putchar() routine. + */ +int +alt_putchar(int c) +{ +#ifdef ALT_SEMIHOSTING + char c1 = (char)(c & 0xff); + return write(STDOUT_FILENO,&c1,1); +#else +#ifdef ALT_USE_DIRECT_DRIVERS + ALT_DRIVER_WRITE_EXTERNS(ALT_STDOUT_DEV); + char c1 = (char)(c & 0xff); + + if (ALT_DRIVER_WRITE(ALT_STDOUT_DEV, &c1, 1, 0) == -1) { + return -1; + } + return c; +#else + return putchar(c); +#endif +#endif +} diff --git a/software/sys_controller_bsp/HAL/src/alt_putstr.c b/software/sys_controller_bsp/HAL/src/alt_putstr.c new file mode 100644 index 0000000..1eadc1f --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_putstr.c @@ -0,0 +1,64 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#ifdef ALT_USE_DIRECT_DRIVERS +#include +#include "system.h" +#include "sys/alt_driver.h" +#include "sys/alt_stdio.h" +#endif +#ifdef ALT_SEMIHOSTING +#include +#include "sys/alt_stdio.h" +#include "unistd.h" +#endif + +/* + * Uses the ALT_DRIVER_WRITE() macro to call directly to driver if available. + * Otherwise, uses newlib provided fputs() routine. + */ +int +alt_putstr(const char* str) +{ +#ifdef ALT_SEMIHOSTING + return write(STDOUT_FILENO,str,strlen(str)); +#else +#ifdef ALT_USE_DIRECT_DRIVERS + ALT_DRIVER_WRITE_EXTERNS(ALT_STDOUT_DEV); + return ALT_DRIVER_WRITE(ALT_STDOUT_DEV, str, strlen(str), 0); +#else + return fputs(str, stdout); +#endif +#endif +} diff --git a/software/sys_controller_bsp/HAL/src/alt_read.c b/software/sys_controller_bsp/HAL/src/alt_read.c new file mode 100644 index 0000000..1c89777 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_read.c @@ -0,0 +1,125 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +/* + * The read() system call is used to read a block of data from a file or device. + * This function simply vectors the request to the device driver associated + * with the input file descriptor "file". + * + * ALT_READ is mapped onto the read() system call in alt_syscall.h + */ + +#ifdef ALT_USE_DIRECT_DRIVERS + +#include "system.h" +#include "sys/alt_driver.h" + +/* + * Provide minimal version that just reads from the stdin device when provided. + */ + +int ALT_READ (int file, void *ptr, size_t len) +{ +#ifdef ALT_STDIN_PRESENT + ALT_DRIVER_READ_EXTERNS(ALT_STDIN_DEV); +#endif + +#if !defined(ALT_STDIN_PRESENT) + /* Generate a link time warning, should this function ever be called. */ + ALT_STUB_WARNING(read); +#endif + + switch (file) { +#ifdef ALT_STDIN_PRESENT + case 0: /* stdin file descriptor */ + return ALT_DRIVER_READ(ALT_STDIN_DEV, ptr, len, 0); +#endif /* ALT_STDIN_PRESENT */ + default: + ALT_ERRNO = EBADFD; + return -1; + } +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +int ALT_READ (int file, void *ptr, size_t len) +{ + alt_fd* fd; + int rval; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + /* + * If the file has not been opened with read access, or if the driver does + * not provide an implementation of read(), generate an error. Otherwise + * call the drivers read() function to process the request. + */ + + if (((fd->fd_flags & O_ACCMODE) != O_WRONLY) && + (fd->dev->read)) + { + if ((rval = fd->dev->read(fd, ptr, len)) < 0) + { + ALT_ERRNO = -rval; + return -1; + } + return rval; + } + else + { + ALT_ERRNO = EACCES; + } + } + else + { + ALT_ERRNO = EBADFD; + } + return -1; +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/alt_release_fd.c b/software/sys_controller_bsp/HAL/src/alt_release_fd.c new file mode 100644 index 0000000..84733a7 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_release_fd.c @@ -0,0 +1,54 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_dev.h" +#include "priv/alt_file.h" + +/* + * alt_release_fd() is called to free an allocated file descriptor. This is + * done by setting the device pointer in the file descriptor structure to zero. + * + * File descriptors correcponding to standard in, standard out and standard + * error cannont be released backed to the pool. They are always reserved. + */ + +void alt_release_fd (int fd) +{ + if (fd > 2) + { + alt_fd_list[fd].fd_flags = 0; + alt_fd_list[fd].dev = 0; + } +} + + + diff --git a/software/sys_controller_bsp/HAL/src/alt_remap_cached.c b/software/sys_controller_bsp/HAL/src/alt_remap_cached.c new file mode 100644 index 0000000..c5f046e --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_remap_cached.c @@ -0,0 +1,55 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003,2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "sys/alt_warning.h" +#include "sys/alt_cache.h" +#include "system.h" + +/* + * Convert a pointer to a block of uncached memory into a block of cached memory. + * Return a pointer that should be used to access the cached memory. + */ + +void* +alt_remap_cached(volatile void* ptr, alt_u32 len) +{ +#if ALT_CPU_DCACHE_SIZE > 0 +#ifdef ALT_CPU_DCACHE_BYPASS_MASK + return (void*) (((alt_u32)ptr) & ~ALT_CPU_DCACHE_BYPASS_MASK); +#else /* No address mask option enabled. */ + /* Generate a link time error, should this function ever be called. */ + ALT_LINK_ERROR("alt_remap_cached() is not available because CPU is not configured to use bit 31 of address to bypass data cache"); + return NULL; +#endif /* No address mask option enabled. */ +#else /* No data cache */ + /* Nothing needs to be done to the pointer. */ + return (void*) ptr; +#endif /* No data cache */ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_remap_uncached.c b/software/sys_controller_bsp/HAL/src/alt_remap_uncached.c new file mode 100644 index 0000000..fc5cf41 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_remap_uncached.c @@ -0,0 +1,54 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003,2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "sys/alt_warning.h" +#include "sys/alt_cache.h" +#include "system.h" + +/* + * Convert a pointer to a block of cached memory into a block of uncached memory. + * Return a pointer that should be used to access the uncached memory. + * + * This routine was created for Nios II Gen1 cores which allow mixing cacheable and + * uncachable data in the same data cache line. So, they could take any memory region + * and make it uncached. However, Nios II Gen2 cores don't support mixing cacheable + * and uncachable data in the same data cache line so require the memory region to + * be aligned to a cache line boundary and must be an integer number of cache line + * bytes in size. So, software on a Nios II Gen2 core shouldn't really be using this + * function so it fails with a link error. + */ + +volatile void* +alt_remap_uncached(void* ptr, alt_u32 len) +{ + /* Generate a link time error, should this function ever be called. */ + ALT_LINK_ERROR("alt_remap_uncached() is not available because Nios II Gen2 cores with data caches don't support mixing cacheable and uncacheable data on the same line."); + return NULL; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_rename.c b/software/sys_controller_bsp/HAL/src/alt_rename.c new file mode 100644 index 0000000..48afac0 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_rename.c @@ -0,0 +1,55 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "os/alt_syscall.h" + +/* + * _rename() is used by newlib to rename an existing file. This is unsupported + * in the HAL environment. However a "do-nothing" implementation is still + * provied for newlib compatability. + * + * ALT_RENAME is mapped onto the _rename() system call in alt_syscall.h + */ + +int ALT_RENAME (char *existing, char *new) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(_rename); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_sbrk.c b/software/sys_controller_bsp/HAL/src/alt_sbrk.c new file mode 100644 index 0000000..b8c3799 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_sbrk.c @@ -0,0 +1,136 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "os/alt_syscall.h" + +#include "sys/alt_irq.h" +#include "sys/alt_stack.h" + +#include "system.h" + +/* + * sbrk() is called to dynamically extend the data segment for the application. + * Thie input argument "incr" is the size of the block to allocate. + * + * This simple implementation does not perform any bounds checking. Memory will + * be allocated, even if the request region colides with the stack or overflows + * the available physical memory. + * + * ALT_SBRK is mapped onto the sbrk() system call in alt_syscall.h + * + * This function is called by the profiling code to allocate memory so must be + * safe if called from an interrupt context. It must also not be instrumented + * because that would lead to an infinate loop. + */ + +extern char __alt_heap_start[]; /* set by linker */ +extern char __alt_heap_limit[]; /* set by linker */ + +static char *heap_end = __alt_heap_start; + +#if defined(ALT_EXCEPTION_STACK) && defined(ALT_STACK_CHECK) +char * alt_exception_old_stack_limit = NULL; +#endif + +caddr_t ALT_SBRK (int incr) __attribute__ ((no_instrument_function )); + +caddr_t ALT_SBRK (int incr) +{ + alt_irq_context context; + char *prev_heap_end; + + context = alt_irq_disable_all(); + + /* Always return data aligned on a word boundary */ + heap_end = (char *)(((unsigned int)heap_end + 3) & ~3); + +#ifdef ALT_MAX_HEAP_BYTES + /* + * User specified a maximum heap size. Return -1 if it would + * be exceeded by this sbrk call. + */ + if (((heap_end + incr) - __alt_heap_start) > ALT_MAX_HEAP_BYTES) { + alt_irq_enable_all(context); + return (caddr_t)-1; + } +#else + if ((heap_end + incr) > __alt_heap_limit) { + alt_irq_enable_all(context); + return (caddr_t)-1; + } +#endif + + prev_heap_end = heap_end; + heap_end += incr; + +#ifdef ALT_STACK_CHECK + /* + * If the stack and heap are contiguous then extending the heap reduces the + * space available for the stack. If we are still using the default stack + * then adjust the stack limit to note this, while checking for stack + * pointer overflow. + * If the stack limit isn't pointing at the top of the heap then the code + * is using a different stack so none of this needs to be done. + */ + + if (alt_stack_limit() == prev_heap_end) + { + if (alt_stack_pointer() <= heap_end) + alt_report_stack_overflow(); + + alt_set_stack_limit(heap_end); + } + +#ifdef ALT_EXCEPTION_STACK + /* + * If we are executing from the exception stack then compare against the + * stack we switched away from as well. The exception stack is a fixed + * size so doesn't need to be checked. + */ + + if (alt_exception_old_stack_limit == prev_heap_end) + { + if (alt_exception_old_stack_limit <= heap_end) + alt_report_stack_overflow(); + + alt_exception_old_stack_limit = heap_end; + } +#endif + +#endif + + alt_irq_enable_all(context); + + return (caddr_t) prev_heap_end; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_settod.c b/software/sys_controller_bsp/HAL/src/alt_settod.c new file mode 100644 index 0000000..59db0f8 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_settod.c @@ -0,0 +1,96 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include "sys/alt_errno.h" +#include "sys/alt_alarm.h" +#include "os/alt_syscall.h" + +/* + * "alt_timezone" and "alt_resettime" are the values of the the reset time and + * time zone set through the last call to settimeofday(). By default they are + * zero initialised. + */ + +extern struct timezone alt_timezone; +extern struct timeval alt_resettime; + +/* + * Macro defining the number of micoseconds in a second. + */ + +#define ALT_US (1000000) + + +/* + * settimeofday() can be called to calibrate the system clock, so that + * subsequent calls to gettimeofday() will return the elapsed "wall clock" + * time. + * + * This is done by updating the global structures "alt_resettime" and + * "alt_timezone" so that an immediate call to gettimeofday() would return + * the value specified by "t" and "tz". + * + * Warning: if this function is called concurrently with a call to + * gettimeofday(), the value returned by gettimeofday() will be unreliable. + * + * ALT_SETTIMEOFDAY is mapped onto the settimeofday() system call in + * alt_syscall.h + */ + +int ALT_SETTIMEOFDAY (const struct timeval *t, + const struct timezone *tz) +{ + alt_u32 nticks = alt_nticks (); + alt_u32 tick_rate = alt_ticks_per_second (); + + /* If there is a system clock available, update the current time */ + + if (tick_rate) + { + alt_resettime.tv_sec = t->tv_sec - nticks/tick_rate; + alt_resettime.tv_usec = t->tv_usec - + ((nticks*(ALT_US/tick_rate))%ALT_US); + + alt_timezone.tz_minuteswest = tz->tz_minuteswest; + alt_timezone.tz_dsttime = tz->tz_dsttime; + + return 0; + } + + /* There's no system clock available */ + + ALT_ERRNO = ENOSYS; + return -1; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_software_exception.S b/software/sys_controller_bsp/HAL/src/alt_software_exception.S new file mode 100644 index 0000000..2142594 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_software_exception.S @@ -0,0 +1,53 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + + /* + * This file provides the global symbol: software_exception. It is provided to + * support legacy code, and should not be used by new software. + * + * It is used by legacy code to invoke the software exception handler as + * defined by version 1.0 of the Nios II kit. It should only be used when you + * are providing your own interrupt entry point, i.e. you are not using + * alt_irq_entry. + */ + +#include "system.h" + + /* + * Pull in the exception handler. + */ + + .globl alt_exception + + .section .exceptions.entry.label, "xa" + + .globl software_exception + .type software_exception, @function +software_exception: diff --git a/software/sys_controller_bsp/HAL/src/alt_stat.c b/software/sys_controller_bsp/HAL/src/alt_stat.c new file mode 100644 index 0000000..44e207b --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_stat.c @@ -0,0 +1,59 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include +#include +#include + +#include "os/alt_syscall.h" + +/* + * The stat() function is similar to the fstat() function in that it is used to + * obtain status information about a file. Instead of using an open file + * descriptor (like fstat()), stat() takes the name of a file as an input + * argument. + * + * ALT_STAT is mapped onto the stat() system call in alt_syscall.h + */ + +int ALT_STAT (const char *file, struct stat *st) +{ + int fd; + int rc; + + fd = open (file, 0); + rc = fstat (fd, st); + close (fd); + + return rc; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_tick.c b/software/sys_controller_bsp/HAL/src/alt_tick.c new file mode 100644 index 0000000..c73488d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_tick.c @@ -0,0 +1,149 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_irq.h" +#include "sys/alt_alarm.h" +#include "os/alt_hooks.h" +#include "alt_types.h" + +/* + * "_alt_tick_rate" is used to store the value of the system clock frequency + * in ticks per second. It is initialised to zero, which corresponds to there + * being no system clock facility available. + */ + +alt_u32 _alt_tick_rate = 0; + +/* + * "_alt_nticks" is the number of system clock ticks that have elapsed since + * reset. + */ + +volatile alt_u32 _alt_nticks = 0; + +/* + * "alt_alarm_list" is the head of a linked list of registered alarms. This is + * initialised to be an empty list. + */ + +ALT_LLIST_HEAD(alt_alarm_list); + +/* + * alt_alarm_stop() is called to remove an alarm from the list of registered + * alarms. Alternatively an alarm can unregister itself by returning zero when + * the alarm executes. + */ + +void alt_alarm_stop (alt_alarm* alarm) +{ + alt_irq_context irq_context; + + irq_context = alt_irq_disable_all(); + alt_llist_remove (&alarm->llist); + alt_irq_enable_all (irq_context); +} + +/* + * alt_tick() is periodically called by the system clock driver in order to + * process the registered list of alarms. Each alarm is registed with a + * callback interval, and a callback function, "callback". + * + * The return value of the callback function indicates how many ticks are to + * elapse until the next callback. A return value of zero indicates that the + * alarm should be deactivated. + * + * alt_tick() is expected to run at interrupt level. + */ + +void alt_tick (void) +{ + alt_alarm* next; + alt_alarm* alarm = (alt_alarm*) alt_alarm_list.next; + + alt_u32 next_callback; + + /* update the tick counter */ + + _alt_nticks++; + + /* process the registered callbacks */ + + while (alarm != (alt_alarm*) &alt_alarm_list) + { + next = (alt_alarm*) alarm->llist.next; + + /* + * Upon the tick-counter rolling over it is safe to clear the + * roll-over flag; once the flag is cleared this (or subsequnt) + * tick events are enabled to generate an alarm event. + */ + if ((alarm->rollover) && (_alt_nticks == 0)) + { + alarm->rollover = 0; + } + + /* if the alarm period has expired, make the callback */ + if ((alarm->time <= _alt_nticks) && (alarm->rollover == 0)) + { + next_callback = alarm->callback (alarm->context); + + /* deactivate the alarm if the return value is zero */ + + if (next_callback == 0) + { + alt_alarm_stop (alarm); + } + else + { + alarm->time += next_callback; + + /* + * If the desired alarm time causes a roll-over, set the rollover + * flag. This will prevent the subsequent tick event from causing + * an alarm too early. + */ + if(alarm->time < _alt_nticks) + { + alarm->rollover = 1; + } + } + } + alarm = next; + } + + /* + * Update the operating system specific timer facilities. + */ + + ALT_OS_TIME_TICK(); +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_times.c b/software/sys_controller_bsp/HAL/src/alt_times.c new file mode 100644 index 0000000..4dd965d --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_times.c @@ -0,0 +1,71 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include + +#include "sys/alt_errno.h" +#include "sys/alt_alarm.h" +#include "os/alt_syscall.h" + +/* + * The times() function is used by newlib to obtain elapsed time information. + * The return value is the elapsed time since reset in system clock ticks. Note + * that this is distinct from the strict Posix version of times(), which should + * return the time since: 0 hours, 0 minutes, 0 seconds, January 1, 1970, GMT. + * + * The input structure is filled in with time accounting information. This + * implementation attributes all cpu time to the system. + * + * ALT_TIMES is mapped onto the times() system call in alt_syscall.h + */ + +clock_t ALT_TIMES (struct tms *buf) +{ + clock_t ticks = alt_nticks(); + + /* If there is no system clock present, generate an error */ + + if (!alt_ticks_per_second()) + { + ALT_ERRNO = ENOSYS; + return 0; + } + + /* Otherwise return the elapsed time */ + + buf->tms_utime = 0; + buf->tms_stime = ticks; + buf->tms_cutime = 0; + buf->tms_cstime = 0; + + return ticks; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_uncached_free.c b/software/sys_controller_bsp/HAL/src/alt_uncached_free.c new file mode 100644 index 0000000..a628c81 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_uncached_free.c @@ -0,0 +1,53 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003,2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "sys/alt_warning.h" +#include "sys/alt_cache.h" +#include "system.h" + +/* + * Free a block of uncached memory. + */ + +void +alt_uncached_free(volatile void* ptr) +{ +#if ALT_CPU_DCACHE_SIZE > 0 +#ifdef ALT_CPU_DCACHE_BYPASS_MASK + free((void*) (((alt_u32)ptr) & ~ALT_CPU_DCACHE_BYPASS_MASK)); +#else /* No address mask option enabled. */ + /* Generate a link time error, should this function ever be called. */ + ALT_LINK_ERROR("alt_uncached_free() is not available because CPU is not configured to use bit 31 of address to bypass data cache"); +#endif /* No address mask option enabled. */ +#else /* No data cache */ + /* Nothing needs to be done to the pointer. */ + free((void*)ptr); +#endif /* No data cache */ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_uncached_malloc.c b/software/sys_controller_bsp/HAL/src/alt_uncached_malloc.c new file mode 100644 index 0000000..270c182 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_uncached_malloc.c @@ -0,0 +1,77 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003,2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include "sys/alt_warning.h" +#include "sys/alt_cache.h" +#include "system.h" + +/* + * Allocate a block of uncached memory. + * Return pointer to the block of memory or NULL if can't allocate it. + */ + +volatile void* +alt_uncached_malloc(size_t size) +{ +#if ALT_CPU_DCACHE_SIZE > 0 +#ifdef ALT_CPU_DCACHE_BYPASS_MASK + + void* ptr; + + /* Round up size to an integer number of data cache lines. Required to guarantee that + * cacheable and non-cacheable data won't be mixed on the same cache line. */ + const size_t num_lines = (size + ALT_CPU_DCACHE_LINE_SIZE - 1) / ALT_CPU_DCACHE_LINE_SIZE; + const size_t aligned_size = num_lines * ALT_CPU_DCACHE_LINE_SIZE; + + /* Use memalign() Newlib routine to allocate starting on a data cache aligned address. + * Required to guarantee that cacheable and non-cacheable data won't be mixed on the + * same cache line. */ + ptr = memalign(ALT_CPU_DCACHE_LINE_SIZE, aligned_size); + + if (ptr == NULL) { + return NULL; /* Out of memory */ + } + + /* Ensure that the memory region isn't in the data cache. */ + alt_dcache_flush(ptr, aligned_size); + + return (volatile void*) (((alt_u32)ptr) | ALT_CPU_DCACHE_BYPASS_MASK); + +#else /* No address mask option enabled. */ + /* Generate a link time error, should this function ever be called. */ + ALT_LINK_ERROR("alt_uncached_malloc() is not available because CPU is not configured to use bit 31 of address to bypass data cache"); + return NULL; +#endif /* No address mask option enabled. */ +#else /* No data cache */ + /* Just use regular malloc. */ + return malloc(size); +#endif /* No data cache */ +} diff --git a/software/sys_controller_bsp/HAL/src/alt_unlink.c b/software/sys_controller_bsp/HAL/src/alt_unlink.c new file mode 100644 index 0000000..29e35d6 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_unlink.c @@ -0,0 +1,55 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "os/alt_syscall.h" + +/* + * unlink() is used by newlib to delete an existing link to a file. This is + * unsupported in the HAL environment. However a "do-nothing" implementation + * is still provied for newlib compatability. + * + * ALT_UNLINK is mapped onto the unlink() system call in alt_syscall.h + */ + +int ALT_UNLINK (char *name) +{ + /* Generate a link time warning, should this function ever be called. */ + + ALT_STUB_WARNING(unlink); + + /* Indicate an error */ + + ALT_ERRNO = ENOSYS; + return -1; +} diff --git a/software/sys_controller_bsp/HAL/src/alt_usleep.c b/software/sys_controller_bsp/HAL/src/alt_usleep.c new file mode 100644 index 0000000..2330eb8 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_usleep.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003 Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * ------------ + * + * Altera does not recommend, suggest or require that this reference design + * file be used in conjunction or combination with any other product. + * + * usleep.c - Microsecond delay routine + */ + +#include + +#include "priv/alt_busy_sleep.h" +#include "os/alt_syscall.h" + +/* + * This function simply calls alt_busy_sleep() to perform the delay. This + * function implements the delay as a calibrated "busy loop". + * + * ALT_USLEEP is mapped onto the usleep() system call in alt_syscall.h + */ + + + +#if defined (__GNUC__) && __GNUC__ >= 4 +int ALT_USLEEP (useconds_t us) +#else +unsigned int ALT_USLEEP (unsigned int us) +#endif +{ + return alt_busy_sleep(us); +} diff --git a/software/sys_controller_bsp/HAL/src/alt_wait.c b/software/sys_controller_bsp/HAL/src/alt_wait.c new file mode 100644 index 0000000..a42f80f --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_wait.c @@ -0,0 +1,52 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2004 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include "sys/alt_errno.h" +#include "os/alt_syscall.h" + +/* + * wait() is used by newlib to wait for all child processes to exit. Since the + * HAL does not support spawning child processes, this returns immediately as + * there can't be anythign to wait for. + * + * ALT_WAIT is mapped onto the wait() system call in alt_syscall.h + */ + +int ALT_WAIT (int *status) +{ + *status = 0; + + ALT_ERRNO = ECHILD; + + return -1; +} + diff --git a/software/sys_controller_bsp/HAL/src/alt_write.c b/software/sys_controller_bsp/HAL/src/alt_write.c new file mode 100644 index 0000000..51debb5 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/alt_write.c @@ -0,0 +1,138 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + +#include +#include + +#include "sys/alt_errno.h" +#include "sys/alt_warning.h" +#include "priv/alt_file.h" +#include "os/alt_syscall.h" + +#include "sys/alt_log_printf.h" + +/* + * The write() system call is used to write a block of data to a file or + * device. This function simply vectors the request to the device driver + * associated with the input file descriptor "file". + * + * ALT_WRITE is mapped onto the write() system call in alt_syscall.h + */ + +#ifdef ALT_USE_DIRECT_DRIVERS + +#include "system.h" +#include "sys/alt_driver.h" + +/* + * Provide minimal version that just writes to the stdout/stderr devices + * when provided. + */ + +int ALT_WRITE (int file, const void *ptr, size_t len) +{ +#ifdef ALT_STDOUT_PRESENT + ALT_DRIVER_WRITE_EXTERNS(ALT_STDOUT_DEV); +#endif +#ifdef ALT_STDERR_PRESENT + ALT_DRIVER_WRITE_EXTERNS(ALT_STDERR_DEV); +#endif + +#if !defined(ALT_STDOUT_PRESENT) && !defined(ALT_STDERR_PRESENT) + /* Generate a link time warning, should this function ever be called. */ + ALT_STUB_WARNING(write); +#endif + + switch (file) { +#ifdef ALT_STDOUT_PRESENT + case 1: /* stdout file descriptor */ + return ALT_DRIVER_WRITE(ALT_STDOUT_DEV, ptr, len, 0); +#endif /* ALT_STDOUT_PRESENT */ +#ifdef ALT_STDERR_PRESENT + case 2: /* stderr file descriptor */ + return ALT_DRIVER_WRITE(ALT_STDERR_DEV, ptr, len, 0); +#endif /* ALT_STDERR_PRESENT */ + default: + ALT_ERRNO = EBADFD; + return -1; + } +} + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +int ALT_WRITE (int file, const void *ptr, size_t len) +{ + alt_fd* fd; + int rval; + + /* + * A common error case is that when the file descriptor was created, the call + * to open() failed resulting in a negative file descriptor. This is trapped + * below so that we don't try and process an invalid file descriptor. + */ + + fd = (file < 0) ? NULL : &alt_fd_list[file]; + + if (fd) + { + /* + * If the file has not been opened with write access, or if the driver does + * not provide an implementation of write(), generate an error. Otherwise + * call the drivers write() function to process the request. + */ + + if (((fd->fd_flags & O_ACCMODE) != O_RDONLY) && fd->dev->write) + { + + /* ALT_LOG - see altera_hal/HAL/inc/sys/alt_log_printf.h */ + ALT_LOG_WRITE_FUNCTION(ptr,len); + + if ((rval = fd->dev->write(fd, ptr, len)) < 0) + { + ALT_ERRNO = -rval; + return -1; + } + return rval; + } + else + { + ALT_ERRNO = EACCES; + } + } + else + { + ALT_ERRNO = EBADFD; + } + return -1; +} + +#endif /* ALT_USE_DIRECT_DRIVERS */ diff --git a/software/sys_controller_bsp/HAL/src/altera_nios2_gen2_irq.c b/software/sys_controller_bsp/HAL/src/altera_nios2_gen2_irq.c new file mode 100644 index 0000000..9849d3f --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/altera_nios2_gen2_irq.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2009 Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * altera_nios2_gen2_irq.c - Support for Nios II internal interrupt controller. + * + */ + +#include "sys/alt_irq.h" +#include "altera_nios2_gen2_irq.h" + +/* + * To initialize the internal interrupt controller, just clear the IENABLE + * register so that all possible IRQs are disabled. + */ +void altera_nios2_gen2_irq_init(void) +{ + NIOS2_WRITE_IENABLE(0); +} diff --git a/software/sys_controller_bsp/HAL/src/crt0.S b/software/sys_controller_bsp/HAL/src/crt0.S new file mode 100644 index 0000000..d6f8dd4 --- /dev/null +++ b/software/sys_controller_bsp/HAL/src/crt0.S @@ -0,0 +1,521 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "system.h" +#include "nios2.h" + +/* Setup header files to work with assembler code. */ +#define ALT_ASM_SRC + +/* Debug logging facility */ +#include "sys/alt_log_printf.h" + +/*************************************************************************\ +| MACROS | +\*************************************************************************/ + +/* + * The new build tools explicitly define macros when alt_load() + * must be called. The define ALT_LOAD_EXPLICITLY_CONTROLLED tells us that + * those macros are controlling if alt_load() needs to be called. + */ +#ifdef ALT_LOAD_EXPLICITLY_CONTROLLED + +/* Need to call alt_load() if any of these sections are being copied. */ +#if defined(ALT_LOAD_COPY_RODATA) || defined(ALT_LOAD_COPY_RWDATA) || defined(ALT_LOAD_COPY_EXCEPTIONS) +#define CALL_ALT_LOAD +#endif + +#else /* !ALT_LOAD_EXPLICITLY_CONTROLLED */ + +/* + * The legacy build tools use the following macros to detect when alt_load() + * needs to be called. + */ + +#define __ALT_LOAD_SECTIONS(res, text, rodata, exc) \ + ((res##_BASE != rodata##_BASE) || \ + (res##_BASE != rwdata##_BASE) || \ + (res##_BASE != exc##_BASE)) + +#define _ALT_LOAD_SECTIONS(res, text, rodata, exc) \ + __ALT_LOAD_SECTIONS(res, text, rodata, exc) + +#define ALT_LOAD_SECTIONS _ALT_LOAD_SECTIONS(ALT_RESET_DEVICE, \ + ALT_RODATA_DEVICE, \ + ALT_RWDATA_DEVICE, \ + ALT_EXCEPTIONS_DEVICE) + +/* Call alt_load() if there is no bootloader and ALT_LOAD_SECTIONS isn't 0. */ +#if defined(ALT_NO_BOOTLOADER) && ALT_LOAD_SECTIONS +#define CALL_ALT_LOAD +#endif + +#endif /* !ALT_LOAD_EXPLICITLY_CONTROLLED */ + +/* + * When the legacy build tools define a macro called ALT_NO_BOOTLOADER, + * it indicates that initialization code is allowed at the reset address. + * The new build tools define a macro called ALT_ALLOW_CODE_AT_RESET for + * the same purpose. + */ +#ifdef ALT_NO_BOOTLOADER +#define ALT_ALLOW_CODE_AT_RESET +#endif + +/*************************************************************************\ +| EXTERNAL REFERENCES | +\*************************************************************************/ + +/* + * The entry point for user code is either "main" in hosted mode, or + * "alt_main" in standalone mode. These are explicitly referenced here, + * to ensure they are built into the executable. This allows the user + * to build them into libraries, rather than supplying them in object + * files at link time. + */ + .globl main + .globl alt_main + +/* + * Create a reference to the software multiply/divide and trap handers, + * so that if they are provided, they will appear in the executable. + */ +#ifndef ALT_NO_INSTRUCTION_EMULATION + .globl alt_exception_muldiv +#endif +#ifdef ALT_TRAP_HANDLER + .globl alt_exception_trap +#endif + +/* + * Linker defined symbols used to initialize bss. + */ +.globl __bss_start +.globl __bss_end + +/*************************************************************************\ +| RESET SECTION (.entry) | +\*************************************************************************/ + +/* + * This is the reset entry point for Nios II. + * + * At reset, only the cache line which contain the reset vector is + * initialized by the hardware. The code within the first cache line + * initializes the remainder of the instruction cache. + */ + + .section .entry, "xa" + .align 5 + +/* + * Explicitly allow the use of r1 (the assembler temporary register) + * within this code. This register is normally reserved for the use of + * the assembler. + */ + .set noat + +/* + * Some tools want to know where the reset vector is. + * Code isn't always provided at the reset vector but at least the + * __reset label always contains the reset vector address because + * it is defined at the start of the .entry section. + */ + + .globl __reset + .type __reset, @function +__reset: + +/* + * Initialize the instruction cache if present (i.e. size > 0) and + * reset code is allowed unless optimizing for RTL simulation. + * RTL simulations can ensure the instruction cache is already initialized + * so skipping this loop speeds up RTL simulation. + * + * When ECC is present, need to execute initi for each word address + * to ensure ECC parity bits in cache RAM get initialized. + */ + +#if NIOS2_ICACHE_SIZE > 0 && defined(ALT_ALLOW_CODE_AT_RESET) && (!defined(ALT_SIM_OPTIMIZE) || defined(NIOS2_ECC_PRESENT)) + /* Assume the instruction cache size is always a power of two. */ +#if NIOS2_ICACHE_SIZE > 0x8000 + movhi r2, %hi(NIOS2_ICACHE_SIZE) +#else + movui r2, NIOS2_ICACHE_SIZE +#endif + +0: + initi r2 + addi r2, r2, -NIOS2_ICACHE_LINE_SIZE + bgt r2, zero, 0b +1: + + /* + * The following debug information tells the ISS not to run the loop above + * but to perform its actions using faster internal code. + */ + .pushsection .debug_alt_sim_info + .int 1, 1, 0b, 1b + .popsection +#endif /* Initialize Instruction Cache */ + +/* + * Jump to the _start entry point in the .text section if reset code + * is allowed or if optimizing for RTL simulation. + */ +#if defined(ALT_ALLOW_CODE_AT_RESET) || defined(ALT_SIM_OPTIMIZE) + /* Jump to the _start entry point in the .text section. */ + movhi r1, %hi(_start) + ori r1, r1, %lo(_start) + jmp r1 + + .size __reset, . - __reset +#endif /* Jump to _start */ + +/* + * When not using exit, provide an _exit symbol to prevent unresolved + * references to _exit from the linker script. + */ +#ifdef ALT_NO_EXIT + .globl _exit +_exit: +#endif + +/*************************************************************************\ +| TEXT SECTION (.text) | +\*************************************************************************/ + +/* + * Start of the .text section, and also the code entry point when + * the code is executed by a bootloader rather than directly from reset. + */ + .section .text + .align 2 + + .globl _start + .type _start, @function +_start: + +#if (NIOS2_NUM_OF_SHADOW_REG_SETS > 0) + /* + * Ensure that the current register set is 0 upon + * entry to this code. Switch register set to 0 by + * writing zero to SSTATUS register and executing an ERET instruction + * to set STATUS.CRS to 0. + */ + + /* Get the current register set number (STATUS.CRS). */ + rdctl r2, status + andi r2, r2, NIOS2_STATUS_CRS_MSK + + /* Skip switching register set if STATUS.CRS is 0. */ + beq r2, zero, 0f + + /* Set SSTATUS to 0 to get to set SSTATUS.PRS to 0. */ + .set nobreak + movui sstatus, 0 + .set break + + /* Switch to register set 0 and jump to label. */ + movhi ea, %hi(0f) + ori ea, ea, %lo(0f) + eret + +0: +#endif /* NIOS2_NUM_OF_SHADOW_REG_SETS > 0 */ + +/* + * Initialize the data cache if present (i.e. size > 0). + * Skip initialization if optimizing for RTL simulation and ECC isn't present. + * RTL simulations can ensure the data cache tag RAM is already initialized + * (but not the data RAM for ECC) so skipping this speeds up RTL simulation. + * + * When ECC is present, need to execute initd for each word address + * to ensure ECC parity bits in data RAM get initialized. + * Otherwise, only need to execute initd for each line address. + */ + +#if NIOS2_DCACHE_SIZE > 0 && (!defined(ALT_SIM_OPTIMIZE) || defined(NIOS2_ECC_PRESENT)) + + /* Assume the data cache size is always a power of two. */ +#if NIOS2_DCACHE_SIZE > 0x8000 + movhi r2, %hi(NIOS2_DCACHE_SIZE) +#else + movui r2, NIOS2_DCACHE_SIZE +#endif + +0: + initd 0(r2) +#ifdef NIOS2_ECC_PRESENT + addi r2, r2, -4 +#else + addi r2, r2, -NIOS2_DCACHE_LINE_SIZE +#endif + bgt r2, zero, 0b +1: + + /* + * The following debug information tells the ISS not to run the loop above + * but to perform its actions using faster internal code. + */ + .pushsection .debug_alt_sim_info + .int 2, 1, 0b, 1b + .popsection +#endif /* Initialize Data Cache */ + + /* Log that caches have been initialized. */ + ALT_LOG_PUTS(alt_log_msg_cache) + + /* Log that the stack pointer is about to be setup. */ + ALT_LOG_PUTS(alt_log_msg_stackpointer) + + /* + * Now that the caches are initialized, set up the stack pointer and global pointer. + * The values provided by the linker are assumed to be correctly aligned. + */ + movhi sp, %hi(__alt_stack_pointer) + ori sp, sp, %lo(__alt_stack_pointer) + movhi gp, %hi(_gp) + ori gp, gp, %lo(_gp) + +#ifdef NIOS2_ECC_PRESENT + /* + * Initialize all general-purpose registers so that ECC can be enabled + * later without accidentally triggering a spurious ECC error. + */ + movui r1, 0 + movui r2, 0 + movui r3, 0 + movui r4, 0 + movui r5, 0 + movui r6, 0 + movui r7, 0 + movui r8, 0 + movui r9, 0 + movui r10, 0 + movui r11, 0 + movui r12, 0 + movui r13, 0 + movui r14, 0 + movui r15, 0 + movui r16, 0 + movui r17, 0 + movui r18, 0 + movui r19, 0 + movui r20, 0 + movui r21, 0 + movui r22, 0 + movui r23, 0 + /* Skip r24 (et) because only exception handler should write it. */ + /* Skip r25 (bt) because only debugger should write it. */ + /* Skip r26 (gp) because it is already been initialized. */ + /* Skip r27 (sp) because it is already been initialized. */ + movui r28, 0 /* fp */ + movui r29, 0 /* ea */ + .set nobreak + movui r30, 0 /* sstatus */ + .set break + movui r31, 0 /* ra */ + +#endif /* NIOS2_ECC_PRESENT */ + +#if (NIOS2_NUM_OF_SHADOW_REG_SETS > 0) + /* + * Setup registers in shadow register sets + * from 1 to NIOS2_NUM_OF_SHADOW_REG_SETS. + */ + + movui r2, 0 /* Contains value written into STATUS */ + movui r3, NIOS2_NUM_OF_SHADOW_REG_SETS /* counter */ + movhi r4, 1 /* Constant to increment STATUS.PRS */ + +.Linitialize_shadow_registers: + /* Increment STATUS.PRS */ + add r2, r2, r4 + wrctl status, r2 + + /* Clear r0 in the shadow register set (not done by hardware) */ + wrprs r0, r0 + + /* Write the GP in previous register set */ + wrprs gp, gp + + /* + * Only write the SP in previous register set + * if using the separate exception stack. For normal case (single stack), + * funnel code would read the SP from previous register set with a RDPRS. + */ +#ifdef ALT_INTERRUPT_STACK + movhi et, %hiadj(__alt_interrupt_stack_pointer) + addi et, et, %lo(__alt_interrupt_stack_pointer) + wrprs sp, et +#endif /* ALT_INTERRUPT_STACK */ + +#ifdef NIOS2_ECC_PRESENT + /* + * Initialize all general-purpose registers so that ECC can be enabled + * later without accidentally triggering a spurious ECC error. + */ + wrprs r1, r0 + wrprs r2, r0 + wrprs r3, r0 + wrprs r4, r0 + wrprs r5, r0 + wrprs r6, r0 + wrprs r7, r0 + wrprs r8, r0 + wrprs r9, r0 + wrprs r10, r0 + wrprs r11, r0 + wrprs r12, r0 + wrprs r13, r0 + wrprs r14, r0 + wrprs r15, r0 + wrprs r16, r0 + wrprs r17, r0 + wrprs r18, r0 + wrprs r19, r0 + wrprs r20, r0 + wrprs r21, r0 + wrprs r22, r0 + wrprs r23, r0 + /* Skip r24 (et) because only exception handler should write it. */ + /* Skip r25 (bt) because only debugger should write it. */ + /* Skip r26 (gp) because it is already been initialized. */ + /* Skip r27 (sp) because it was initialized above or will be by a rdprs if not above */ + wrprs r28, r0 /* fp */ + wrprs r29, r0 /* ea */ + wrprs r30, r0 /* ba */ + wrprs r31, r0 /* ra */ +#endif /* NIOS2_ECC_PRESENT */ + + /* Decrement shadow register set counter */ + addi r3, r3, -1 + + /* Done if index is 0. */ + bne r3, zero, .Linitialize_shadow_registers +#endif /* (NIOS2_NUM_OF_SHADOW_REG_SETS > 0) */ + +/* + * Clear the BSS if not optimizing for RTL simulation. + * + * This uses the symbols: __bss_start and __bss_end, which are defined + * by the linker script. They mark the begining and the end of the bss + * region. The linker script guarantees that these values are word aligned. + */ +#ifndef ALT_SIM_OPTIMIZE + /* Log that the BSS is about to be cleared. */ + ALT_LOG_PUTS(alt_log_msg_bss) + + movhi r2, %hi(__bss_start) + ori r2, r2, %lo(__bss_start) + + movhi r3, %hi(__bss_end) + ori r3, r3, %lo(__bss_end) + + beq r2, r3, 1f + +0: + stw zero, (r2) + addi r2, r2, 4 + bltu r2, r3, 0b + +1: + + /* + * The following debug information tells the ISS not to run the loop above + * but to perform its actions using faster internal code. + */ + .pushsection .debug_alt_sim_info + .int 3, 1, 0b, 1b + .popsection +#endif /* ALT_SIM_OPTIMIZE */ + +/* + * Turn off the use of r1 (the assembler temporary register) + * so that call instructions can be safely relaxed across a + * 256MB boundary if needed + */ + .set at + +/* + * The alt_load() facility is normally used when there is no bootloader. + * It copies some sections into RAM so it acts like a mini-bootloader. + */ +#ifdef CALL_ALT_LOAD + +#ifdef ALT_STACK_CHECK + /* + * If the user has selected stack checking then we need to set up a safe + * value in the stack limit register so that the relocation functions + * don't think the stack has overflowed (the contents of the rwdata + * section aren't defined until alt_load() has been called). + */ + mov et, zero +#endif + + call alt_load + +#endif /* CALL_ALT_LOAD */ + +#ifdef ALT_STACK_CHECK + /* + * Set up the stack limit (if required). The linker has set up the + * copy of the variable which is in memory. + */ + + ldw et, %gprel(alt_stack_limit_value)(gp) +#endif + + /* Log that alt_main is about to be called. */ + ALT_LOG_PUTS(alt_log_msg_alt_main) + + /* Call the C entry point. It should never return. */ + call alt_main + + /* Wait in infinite loop in case alt_main does return. */ +alt_after_alt_main: + br alt_after_alt_main + + .size _start, . - _start + +/* + * Add information about the stack base if stack overflow checking is enabled. + */ +#ifdef ALT_STACK_CHECK + .globl alt_stack_limit_value + .section .sdata,"aws",@progbits + .align 2 + .type alt_stack_limit_value, @object + .size alt_stack_limit_value, 4 +alt_stack_limit_value: + .long __alt_stack_limit +#endif diff --git a/software/sys_controller_bsp/Makefile b/software/sys_controller_bsp/Makefile new file mode 100644 index 0000000..2ecc07c --- /dev/null +++ b/software/sys_controller_bsp/Makefile @@ -0,0 +1,790 @@ +#------------------------------------------------------------------------------ +# BSP MAKEFILE +# +# This makefile was automatically generated by the nios2-bsp-generate-files +# command. Its purpose is to build a custom Board Support Package (BSP) +# targeting a specific Nios II processor in an SOPC Builder-based design. +# +# To create an application or library Makefile which uses this BSP, try the +# nios2-app-generate-makefile or nios2-lib-generate-makefile commands. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# TOOLS +#------------------------------------------------------------------------------ + +MKDIR := mkdir -p +ECHO := echo +SPACE := $(empty) $(empty) + +#------------------------------------------------------------------------------ +# The adjust-path macro +# +# If COMSPEC is defined, Make is launched from Windows through +# Cygwin. This adjust-path macro will call 'cygpath -u' on all +# paths to ensure they are readable by Make. +# +# If COMSPEC is not defined, Make is launched from *nix, and no adjustment +# is necessary +#------------------------------------------------------------------------------ + +ifndef COMSPEC +ifdef ComSpec +COMSPEC = $(ComSpec) +endif # ComSpec +endif # !COMSPEC + +ifdef COMSPEC + adjust-path = $(subst $(SPACE),\$(SPACE),$(shell cygpath -u "$1")) + adjust-path-mixed = $(subst $(SPACE),\$(SPACE),$(shell cygpath -m "$1")) +else + adjust-path = $(subst $(SPACE),\$(SPACE),$1) + adjust-path-mixed = $(subst $(SPACE),\$(SPACE),$1) +endif + +#------------------------------------------------------------------------------ +# DEFAULT TARGET +# +# The default target, "all", must appear before any other target in the +# Makefile. Note that extra prerequisites are added to the "all" rule later. +#------------------------------------------------------------------------------ +.PHONY: all +all: + @$(ECHO) [BSP build complete] + + +#------------------------------------------------------------------------------ +# PATHS & DIRECTORY NAMES +# +# Explicitly locate absolute path of the BSP root +#------------------------------------------------------------------------------ + +BSP_ROOT_DIR := . + +# Define absolute path to the root of the BSP. +ABS_BSP_ROOT := $(call adjust-path-mixed,$(shell pwd)) + +# Stash all BSP object files here +OBJ_DIR := ./obj + + +#------------------------------------------------------------------------------ +# MANAGED CONTENT +# +# All content between the lines "START MANAGED" and "END MANAGED" below is +# generated based on variables in the BSP settings file when the +# nios2-bsp-generate-files command is invoked. If you wish to persist any +# information pertaining to the build process, it is recomended that you +# utilize the BSP settings mechanism to do so. +# +# Note that most variable assignments in this section have a corresponding BSP +# setting that can be changed by using the nios2-bsp-create-settings or +# nios2-bsp-update-settings command before nios2-bsp-generate-files; if you +# want any variable set to a specific value when this Makefile is re-generated +# (to prevent hand-edits from being over-written), use the BSP settings +# facilities above. +#------------------------------------------------------------------------------ + +#START MANAGED + +# The following TYPE comment allows tools to identify the 'type' of target this +# makefile is associated with. +# TYPE: BSP_PRIVATE_MAKEFILE + +# This following VERSION comment indicates the version of the tool used to +# generate this makefile. A makefile variable is provided for VERSION as well. +# ACDS_VERSION: 15.1 +ACDS_VERSION := 15.1 + +# This following BUILD_NUMBER comment indicates the build number of the tool +# used to generate this makefile. +# BUILD_NUMBER: 185 + +SETTINGS_FILE := settings.bsp +SOPC_FILE := ../../sys.sopcinfo + +#------------------------------------------------------------------------------- +# TOOL & COMMAND DEFINITIONS +# +# The base command for each build operation are expressed here. Additional +# switches may be expressed here. They will run for all instances of the +# utility. +#------------------------------------------------------------------------------- + +# Archiver command. Creates library files. +AR = nios2-elf-ar + +# Assembler command. Note that CC is used for .S files. +AS = nios2-elf-gcc + +# Custom flags only passed to the archiver. This content of this variable is +# directly passed to the archiver rather than the more standard "ARFLAGS". The +# reason for this is that GNU Make assumes some default content in ARFLAGS. +# This setting defines the value of BSP_ARFLAGS in Makefile. +BSP_ARFLAGS = -src + +# Custom flags only passed to the assembler. This setting defines the value of +# BSP_ASFLAGS in Makefile. +BSP_ASFLAGS = -Wa,-gdwarf2 + +# C/C++ compiler optimization level. "-O0" = no optimization,"-O2" = "normal" +# optimization, etc. "-O0" is recommended for code that you want to debug since +# compiler optimization can remove variables and produce non-sequential +# execution of code while debugging. This setting defines the value of +# BSP_CFLAGS_OPTIMIZATION in Makefile. +BSP_CFLAGS_OPTIMIZATION = -Os + +# C/C++ compiler warning level. "-Wall" is commonly used.This setting defines +# the value of BSP_CFLAGS_WARNINGS in Makefile. +BSP_CFLAGS_WARNINGS = -Wall + +# C compiler command. +CC = nios2-elf-gcc -xc + +# C++ compiler command. +CXX = nios2-elf-gcc -xc++ + +# Command used to remove files during 'clean' target. +RM = rm -f + + +#------------------------------------------------------------------------------- +# BUILD PRE & POST PROCESS COMMANDS +# +# The following variables are treated as shell commands in the rule +# definitions for each file-type associated with the BSP build, as well as +# commands run at the beginning and end of the entire BSP build operation. +# Pre-process commands are executed before the relevant command (for example, +# a command defined in the "CC_PRE_PROCESS" variable executes before the C +# compiler for building .c files), while post-process commands are executed +# immediately afterwards. +# +# You can view each pre/post-process command in the "Build Rules: All & +# Clean", "Pattern Rules to Build Objects", and "Library Rules" sections of +# this Makefile. +#------------------------------------------------------------------------------- + + +#------------------------------------------------------------------------------- +# BSP SOURCE BUILD SETTINGS (FLAG GENERATION) +# +# Software build settings such as compiler optimization, debug level, warning +# flags, etc., may be defined in the following variables. The variables below +# are concatenated together in the 'Flags' section of this Makefile to form +# final variables of flags passed to the build tools. +# +# These settings are considered private to the BSP and apply to all library & +# driver files in it; they do NOT automatically propagate to, for example, the +# build settings for an application. +# # For additional detail and syntax requirements, please refer to GCC help +# (example: "nios2-elf-gcc --help --verbose"). +# +# Unless indicated otherwise, multiple entries in each variable should be +# space-separated. +#------------------------------------------------------------------------------- + +# Altera HAL alt_sys_init.c generated source file +GENERATED_C_FILES := $(ABS_BSP_ROOT)/alt_sys_init.c +GENERATED_C_LIB_SRCS += alt_sys_init.c + + +#------------------------------------------------------------------------------- +# BSP SOURCE FILE LISTING +# +# All source files that comprise the BSP are listed here, along with path +# information to each file expressed relative to the BSP root. The precise +# list and location of each file is derived from the driver, operating system, +# or software package source file declarations. +# +# Following specification of the source files for each component, driver, etc., +# each source file type (C, assembly, etc.) is concatenated together and used +# to construct a list of objects. Pattern rules to build each object are then +# used to build each file. +#------------------------------------------------------------------------------- + +# altera_up_sd_card_avalon_interface_mod_driver sources root +Altera_UP_SD_Card_Avalon_Interface_mod_driver_SRCS_ROOT := drivers + +# altera_up_sd_card_avalon_interface_mod_driver sources +Altera_UP_SD_Card_Avalon_Interface_mod_driver_C_LIB_SRCS := \ + $(Altera_UP_SD_Card_Avalon_Interface_mod_driver_SRCS_ROOT)/src/Altera_UP_SD_Card_Avalon_Interface_mod.c + +# altera_avalon_jtag_uart_driver sources root +altera_avalon_jtag_uart_driver_SRCS_ROOT := drivers + +# altera_avalon_jtag_uart_driver sources +altera_avalon_jtag_uart_driver_C_LIB_SRCS := \ + $(altera_avalon_jtag_uart_driver_SRCS_ROOT)/src/altera_avalon_jtag_uart_init.c \ + $(altera_avalon_jtag_uart_driver_SRCS_ROOT)/src/altera_avalon_jtag_uart_read.c \ + $(altera_avalon_jtag_uart_driver_SRCS_ROOT)/src/altera_avalon_jtag_uart_write.c \ + $(altera_avalon_jtag_uart_driver_SRCS_ROOT)/src/altera_avalon_jtag_uart_ioctl.c \ + $(altera_avalon_jtag_uart_driver_SRCS_ROOT)/src/altera_avalon_jtag_uart_fd.c + +# altera_avalon_pio_driver sources root +altera_avalon_pio_driver_SRCS_ROOT := drivers + +# altera_avalon_pio_driver sources +# altera_epcq_controller_mod_driver sources root +altera_epcq_controller_mod_driver_SRCS_ROOT := drivers + +# altera_epcq_controller_mod_driver sources +altera_epcq_controller_mod_driver_C_LIB_SRCS := \ + $(altera_epcq_controller_mod_driver_SRCS_ROOT)/src/altera_epcq_controller_mod.c + +# altera_nios2_gen2_hal_driver sources root +altera_nios2_gen2_hal_driver_SRCS_ROOT := HAL + +# altera_nios2_gen2_hal_driver sources +altera_nios2_gen2_hal_driver_C_LIB_SRCS := \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/altera_nios2_gen2_irq.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_usleep.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_busy_sleep.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_irq_vars.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_icache_flush.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_icache_flush_all.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_dcache_flush.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_dcache_flush_all.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_dcache_flush_no_writeback.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_ecc_fatal_exception.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_instruction_exception_entry.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_irq_register.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_iic.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_remap_cached.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_remap_uncached.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_uncached_free.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_uncached_malloc.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_do_ctors.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_do_dtors.c \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_gmon.c + +altera_nios2_gen2_hal_driver_ASM_LIB_SRCS := \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_ecc_fatal_entry.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_exception_entry.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_exception_trap.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_exception_muldiv.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_irq_entry.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_software_exception.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_mcount.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/alt_log_macro.S \ + $(altera_nios2_gen2_hal_driver_SRCS_ROOT)/src/crt0.S + +# hal sources root +hal_SRCS_ROOT := HAL + +# hal sources +hal_C_LIB_SRCS := \ + $(hal_SRCS_ROOT)/src/alt_alarm_start.c \ + $(hal_SRCS_ROOT)/src/alt_close.c \ + $(hal_SRCS_ROOT)/src/alt_dev.c \ + $(hal_SRCS_ROOT)/src/alt_dev_llist_insert.c \ + $(hal_SRCS_ROOT)/src/alt_dma_rxchan_open.c \ + $(hal_SRCS_ROOT)/src/alt_dma_txchan_open.c \ + $(hal_SRCS_ROOT)/src/alt_environ.c \ + $(hal_SRCS_ROOT)/src/alt_env_lock.c \ + $(hal_SRCS_ROOT)/src/alt_errno.c \ + $(hal_SRCS_ROOT)/src/alt_execve.c \ + $(hal_SRCS_ROOT)/src/alt_exit.c \ + $(hal_SRCS_ROOT)/src/alt_fcntl.c \ + $(hal_SRCS_ROOT)/src/alt_fd_lock.c \ + $(hal_SRCS_ROOT)/src/alt_fd_unlock.c \ + $(hal_SRCS_ROOT)/src/alt_find_dev.c \ + $(hal_SRCS_ROOT)/src/alt_find_file.c \ + $(hal_SRCS_ROOT)/src/alt_flash_dev.c \ + $(hal_SRCS_ROOT)/src/alt_fork.c \ + $(hal_SRCS_ROOT)/src/alt_fs_reg.c \ + $(hal_SRCS_ROOT)/src/alt_fstat.c \ + $(hal_SRCS_ROOT)/src/alt_get_fd.c \ + $(hal_SRCS_ROOT)/src/alt_getchar.c \ + $(hal_SRCS_ROOT)/src/alt_getpid.c \ + $(hal_SRCS_ROOT)/src/alt_gettod.c \ + $(hal_SRCS_ROOT)/src/alt_iic_isr_register.c \ + $(hal_SRCS_ROOT)/src/alt_instruction_exception_register.c \ + $(hal_SRCS_ROOT)/src/alt_ioctl.c \ + $(hal_SRCS_ROOT)/src/alt_io_redirect.c \ + $(hal_SRCS_ROOT)/src/alt_irq_handler.c \ + $(hal_SRCS_ROOT)/src/alt_isatty.c \ + $(hal_SRCS_ROOT)/src/alt_kill.c \ + $(hal_SRCS_ROOT)/src/alt_link.c \ + $(hal_SRCS_ROOT)/src/alt_load.c \ + $(hal_SRCS_ROOT)/src/alt_log_printf.c \ + $(hal_SRCS_ROOT)/src/alt_lseek.c \ + $(hal_SRCS_ROOT)/src/alt_main.c \ + $(hal_SRCS_ROOT)/src/alt_malloc_lock.c \ + $(hal_SRCS_ROOT)/src/alt_open.c \ + $(hal_SRCS_ROOT)/src/alt_printf.c \ + $(hal_SRCS_ROOT)/src/alt_putchar.c \ + $(hal_SRCS_ROOT)/src/alt_putcharbuf.c \ + $(hal_SRCS_ROOT)/src/alt_putstr.c \ + $(hal_SRCS_ROOT)/src/alt_read.c \ + $(hal_SRCS_ROOT)/src/alt_release_fd.c \ + $(hal_SRCS_ROOT)/src/alt_rename.c \ + $(hal_SRCS_ROOT)/src/alt_sbrk.c \ + $(hal_SRCS_ROOT)/src/alt_settod.c \ + $(hal_SRCS_ROOT)/src/alt_stat.c \ + $(hal_SRCS_ROOT)/src/alt_tick.c \ + $(hal_SRCS_ROOT)/src/alt_times.c \ + $(hal_SRCS_ROOT)/src/alt_unlink.c \ + $(hal_SRCS_ROOT)/src/alt_wait.c \ + $(hal_SRCS_ROOT)/src/alt_write.c + +# i2c_opencores_driver sources root +i2c_opencores_driver_SRCS_ROOT := drivers + +# i2c_opencores_driver sources +i2c_opencores_driver_C_LIB_SRCS := \ + $(i2c_opencores_driver_SRCS_ROOT)/src/i2c_opencores.c + +# nios2_hw_crc32_driver sources root +nios2_hw_crc32_driver_SRCS_ROOT := drivers + +# nios2_hw_crc32_driver sources +nios2_hw_crc32_driver_C_LIB_SRCS := \ + $(nios2_hw_crc32_driver_SRCS_ROOT)/src/ci_crc.c \ + $(nios2_hw_crc32_driver_SRCS_ROOT)/src/crc.c + + +# Assemble all component C source files +COMPONENT_C_LIB_SRCS += \ + $(Altera_UP_SD_Card_Avalon_Interface_mod_driver_C_LIB_SRCS) \ + $(altera_avalon_jtag_uart_driver_C_LIB_SRCS) \ + $(altera_epcq_controller_mod_driver_C_LIB_SRCS) \ + $(altera_nios2_gen2_hal_driver_C_LIB_SRCS) \ + $(hal_C_LIB_SRCS) \ + $(i2c_opencores_driver_C_LIB_SRCS) \ + $(nios2_hw_crc32_driver_C_LIB_SRCS) + +# Assemble all component assembly source files +COMPONENT_ASM_LIB_SRCS += \ + $(altera_nios2_gen2_hal_driver_ASM_LIB_SRCS) + +# Assemble all component C++ source files +COMPONENT_CPP_LIB_SRCS += \ + +#END MANAGED + +#------------------------------------------------------------------------------ +# PUBLIC.MK +# +# The generated public.mk file contains BSP information that is shared with +# other external makefiles, such as a Nios II application makefile. System- +# dependent information such as hardware-specific compiler flags and +# simulation file generation are stored here. +# +# In addition, public.mk contains include paths that various software, +# such as a device driver, may need for the C compiler. These paths are +# written to public.mk with respect to the BSP root. In public.mk, each +# path is prefixed with a special variable, $(ALT_LIBRARY_ROOT_DIR). The +# purpose of this variable is to allow an external Makefile to append on +# path information to precisely locate paths expressed in public.mk +# Since this is the BSP Makefile, we set ALT_LIBRARY_ROOT_DIR to point right +# here ("."), at the BSP root. +# +# ALT_LIBRARY_ROOT_DIR must always be set before public.mk is included. +#------------------------------------------------------------------------------ +ALT_LIBRARY_ROOT_DIR := . +include public.mk + + +#------------------------------------------------------------------------------ +# FLAGS +# +# Include paths for BSP files are written into the public.mk file and must +# be added to the existing list of pre-processor flags. In addition, "hooks" +# for standard flags left intentionally empty (CFLAGS, CPPFLAGS, ASFLAGS, +# and CXXFLAGS) are provided for conveniently adding to the relevant flags +# on the command-line or via script that calls make. +#------------------------------------------------------------------------------ +# Assemble final list of compiler flags from generated content +BSP_CFLAGS += \ + $(BSP_CFLAGS_DEFINED_SYMBOLS) \ + $(BSP_CFLAGS_UNDEFINED_SYMBOLS) \ + $(BSP_CFLAGS_OPTIMIZATION) \ + $(BSP_CFLAGS_DEBUG) \ + $(BSP_CFLAGS_WARNINGS) \ + $(BSP_CFLAGS_USER_FLAGS) \ + $(ALT_CFLAGS) \ + $(CFLAGS) + +# Make ready the final list of include directories and other C pre-processor +# flags. Each include path is made ready by prefixing it with "-I". +BSP_CPPFLAGS += \ + $(addprefix -I, $(BSP_INC_DIRS)) \ + $(addprefix -I, $(ALT_INCLUDE_DIRS)) \ + $(ALT_CPPFLAGS) \ + $(CPPFLAGS) + +# Finish off assembler flags with any user-provided flags +BSP_ASFLAGS += $(ASFLAGS) + +# Finish off C++ flags with any user-provided flags +BSP_CXXFLAGS += $(CXXFLAGS) + +# And finally, the ordered list +C_SRCS += $(GENERATED_C_LIB_SRCS) \ + $(COMPONENT_C_LIB_SRCS) + +CXX_SRCS += $(GENERATED_CPP_LIB_SRCS) \ + $(COMPONENT_CPP_LIB_SRCS) + +ASM_SRCS += $(GENERATED_ASM_LIB_SRCS) \ + $(COMPONENT_ASM_LIB_SRCS) + + +#------------------------------------------------------------------------------ +# LIST OF GENERATED FILES +# +# A Nios II BSP relies on the generation of several source files used +# by both the BSP and any applications referencing the BSP. +#------------------------------------------------------------------------------ + + +GENERATED_H_FILES := $(ABS_BSP_ROOT)/system.h + +GENERATED_LINKER_SCRIPT := $(ABS_BSP_ROOT)/linker.x + +GENERATED_FILES += $(GENERATED_H_FILES) \ + $(GENERATED_LINKER_SCRIPT) + + +#------------------------------------------------------------------------------ +# SETUP TO BUILD OBJECTS +# +# List of object files which are to be built. This is constructed from the input +# list of C source files (C_SRCS), C++ source files (CXX_SRCS), and assembler +# source file (ASM_SRCS). The permitted file extensions are: +# +# .c .C - for C files +# .cxx .cc .cpp .CXX .CC .CPP - for C++ files +# .S .s - for assembly files +# +# Extended description: The list of objects is a sorted list (duplicates +# removed) of all possible objects, placed beneath the ./obj directory, +# including any path information stored in the "*_SRCS" variable. The +# "patsubst" commands are used to concatenate together multiple file suffix +# types for common files (i.e. c++ as .cxx, .cc, .cpp). +# +# File extensions are case-insensitive in build rules with the exception of +# assembly sources. Nios II assembly sources with the ".S" extension are first +# run through the C preprocessor. Sources with the ".s" extension are not. +#------------------------------------------------------------------------------ +OBJS = $(sort $(addprefix $(OBJ_DIR)/, \ + $(patsubst %.c, %.o, $(patsubst %.C, %.o, $(C_SRCS))) \ + $(patsubst %.cxx, %.o, $(patsubst %.CXX, %.o, \ + $(patsubst %.cc, %.o, $(patsubst %.CC, %.o, \ + $(patsubst %.cpp, %.o, $(patsubst %.CPP, %.o, \ + $(CXX_SRCS) )))))) \ + $(patsubst %.S, %.o, $(patsubst %.s, %.o, $(ASM_SRCS))) )) + +# List of dependancy files for each object file. +DEPS = $(OBJS:.o=.d) + + +# Rules to force your project to rebuild or relink +# .force_relink file will cause any application that depends on this project to relink +# .force_rebuild file will cause this project to rebuild object files +# .force_rebuild_all file will cause this project and any project that depends on this project to rebuild object files + +FORCE_RELINK_DEP := .force_relink +FORCE_REBUILD_DEP := .force_rebuild +FORCE_REBUILD_ALL_DEP := .force_rebuild_all +FORCE_REBUILD_DEP_LIST := $(FORCE_RELINK_DEP) $(FORCE_REBUILD_DEP) $(FORCE_REBUILD_ALL_DEP) + +$(FORCE_REBUILD_DEP_LIST): + +$(OBJS): $(wildcard $(FORCE_REBUILD_DEP)) $(wildcard $(FORCE_REBUILD_ALL_DEP)) + + +#------------------------------------------------------------------------------ +# BUILD RULES: ALL & CLEAN +#------------------------------------------------------------------------------ +.DELETE_ON_ERROR: + +.PHONY: all +all: build_pre_process +all: Makefile $(GENERATED_FILES) $(BSP_LIB) $(NEWLIB_DIR) +all: build_post_process + + +# clean: remove .o/.a/.d +.PHONY: clean +clean: + @$(RM) -r $(BSP_LIB) $(OBJ_DIR) $(FORCE_REBUILD_DEP_LIST) +ifneq ($(wildcard $(NEWLIB_DIR)),) + @$(RM) -r $(NEWLIB_DIR) +endif + @$(ECHO) [BSP clean complete] + + +#------------------------------------------------------------------------------ +# BUILD PRE/POST PROCESS +#------------------------------------------------------------------------------ +build_pre_process : + $(BUILD_PRE_PROCESS) + +build_post_process : + $(BUILD_POST_PROCESS) + +.PHONY: build_pre_process build_post_process + + + +#------------------------------------------------------------------------------ +# MAKEFILE UP TO DATE? +# +# Is this very Makefile up to date? Someone may have changed the BSP settings +# file or the associated target hardware. +#------------------------------------------------------------------------------ +# Skip this check when clean is the only target +ifneq ($(MAKECMDGOALS),clean) + +ifneq ($(wildcard $(SETTINGS_FILE)),$(SETTINGS_FILE)) +$(warning Warning: BSP Settings File $(SETTINGS_FILE) could not be found.) +endif + +Makefile: $(wildcard $(SETTINGS_FILE)) + @$(ECHO) Makefile not up to date. + @$(ECHO) $(SETTINGS_FILE) has been modified since the BSP Makefile was generated. + @$(ECHO) + @$(ECHO) Generate the BSP to update the Makefile, and then build again. + @$(ECHO) + @$(ECHO) To generate from Eclipse: + @$(ECHO) " 1. Right-click the BSP project." + @$(ECHO) " 2. In the Nios II Menu, click Generate BSP." + @$(ECHO) + @$(ECHO) To generate from the command line: + @$(ECHO) " nios2-bsp-generate-files --settings= --bsp-dir=" + @$(ECHO) + @exit 1 + +ifneq ($(wildcard $(SOPC_FILE)),$(SOPC_FILE)) +$(warning Warning: SOPC File $(SOPC_FILE) could not be found.) +endif + +public.mk: $(wildcard $(SOPC_FILE)) + @$(ECHO) Makefile not up to date. + @$(ECHO) $(SOPC_FILE) has been modified since the BSP was generated. + @$(ECHO) + @$(ECHO) Generate the BSP to update the Makefile, and then build again. + @$(ECHO) + @$(ECHO) To generate from Eclipse: + @$(ECHO) " 1. Right-click the BSP project." + @$(ECHO) " 2. In the Nios II Menu, click Generate BSP." + @$(ECHO) + @$(ECHO) To generate from the command line: + @$(ECHO) " nios2-bsp-generate-files --settings= --bsp-dir=" + @$(ECHO) + @exit 1 + +endif # $(MAKECMDGOALS) != clean + +#------------------------------------------------------------------------------ +# PATTERN RULES TO BUILD OBJECTS +#------------------------------------------------------------------------------ +$(OBJ_DIR)/%.o: %.c + @$(ECHO) Compiling $( + +/* + * Device headers + */ + +#include "altera_nios2_gen2_irq.h" +#include "Altera_UP_SD_Card_Avalon_Interface_mod.h" +#include "altera_avalon_jtag_uart.h" +#include "altera_epcq_controller_mod.h" +#include "i2c_opencores.h" + +/* + * Allocate the device storage + */ + +ALTERA_NIOS2_GEN2_IRQ_INSTANCE ( NIOS2_QSYS_0, nios2_qsys_0); +ALTERA_AVALON_JTAG_UART_INSTANCE ( JTAG_UART_0, jtag_uart_0); +ALTERA_EPCQ_CONTROLLER_MOD_AVL_MEM_AVL_CSR_INSTANCE ( EPCQ_CONTROLLER_0, EPCQ_CONTROLLER_0_AVL_MEM, EPCQ_CONTROLLER_0_AVL_CSR, epcq_controller_0); +ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INSTANCE ( ALTERA_UP_SD_CARD_AVALON_INTERFACE_0, Altera_UP_SD_Card_Avalon_Interface_0); +I2C_OPENCORES_INSTANCE ( I2C_OPENCORES_0, i2c_opencores_0); + +/* + * Initialize the interrupt controller devices + * and then enable interrupts in the CPU. + * Called before alt_sys_init(). + * The "base" parameter is ignored and only + * present for backwards-compatibility. + */ + +void alt_irq_init ( const void* base ) +{ + ALTERA_NIOS2_GEN2_IRQ_INIT ( NIOS2_QSYS_0, nios2_qsys_0); + alt_irq_cpu_enable_interrupts(); +} + +/* + * Initialize the non-interrupt controller devices. + * Called after alt_irq_init(). + */ + +void alt_sys_init( void ) +{ + ALTERA_AVALON_JTAG_UART_INIT ( JTAG_UART_0, jtag_uart_0); + ALTERA_EPCQ_CONTROLLER_MOD_INIT ( EPCQ_CONTROLLER_0, epcq_controller_0); + ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INIT ( ALTERA_UP_SD_CARD_AVALON_INTERFACE_0, Altera_UP_SD_Card_Avalon_Interface_0); + I2C_OPENCORES_INIT ( I2C_OPENCORES_0, i2c_opencores_0); +} diff --git a/software/sys_controller_bsp/create-this-bsp b/software/sys_controller_bsp/create-this-bsp new file mode 100755 index 0000000..781754e --- /dev/null +++ b/software/sys_controller_bsp/create-this-bsp @@ -0,0 +1,52 @@ +#!/bin/bash +# +# This script creates the ucosii_net_zipfs Board Support Package (BSP). + +BSP_TYPE=hal +BSP_DIR=. +SOPC_DIR=../../ +SOPC_FILE=../../sys.sopcinfo +NIOS2_BSP_ARGS="" +CPU_NAME= + +if [ -n "$CPU_NAME" ]; then + NIOS2_BSP_ARGS="$NIOS2_BSP_ARGS --cpu-name $CPU_NAME" +fi + +# Don't run make if create-this-app script is called with --no-make arg +SKIP_MAKE= +while [ $# -gt 0 ] +do + case "$1" in + --no-make) + SKIP_MAKE=1 + ;; + *) + NIOS2_BSP_ARGS="$NIOS2_BSP_ARGS $1" + ;; + esac + shift +done + + +# Run nios2-bsp utility to create a hal BSP in this directory +# for the system with a .sopc file in $SOPC_FILE. +# Deprecating $SOPC_DIR in 10.1. Multiple .sopcinfo files in a directory may exist. + +if [ -z "$SOPC_FILE" ]; then + echo "WARNING: Use of a directory for locating a .sopcinfo file is deprecated in 10.1. Multiple .sopcinfo files may exist. You must specify the full .sopcinfo path." + cmd="nios2-bsp $BSP_TYPE $BSP_DIR $SOPC_DIR $NIOS2_BSP_ARGS" +else + cmd="nios2-bsp $BSP_TYPE $BSP_DIR $SOPC_FILE $NIOS2_BSP_ARGS" +fi + + +echo "create-this-bsp: Running \"$cmd\"" +$cmd || { + echo "$cmd failed" + exit 1 +} +if [ -z "$SKIP_MAKE" ]; then + echo "create-this-bsp: Running make" + make +fi diff --git a/software/sys_controller_bsp/drivers/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h b/software/sys_controller_bsp/drivers/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h new file mode 100644 index 0000000..4e1dbef --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/Altera_UP_SD_Card_Avalon_Interface_mod.h @@ -0,0 +1,166 @@ +#ifndef __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ +#define __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define SD_RAW_IFACE + +/* + * Device structure definition. Each instance of the driver uses one + * of these structures to hold its associated state. + */ +typedef struct alt_up_sd_card_dev { + /// @brief character mode device structure + /// @sa Developing Device Drivers for the HAL in Nios II Software Developer's Handbook + alt_dev dev; + /// @brief the base address of the device + unsigned int base; + +} alt_up_sd_card_dev; + +#ifndef bool + typedef enum e_bool { false = 0, true = 1 } bool; +#endif + +////////////////////////////////////////////////////////////////////////// +// HAL system functions + +alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char *name); +/* Open an SD Card Interface if it is connected to the system. */ + + +bool alt_up_sd_card_is_Present(void); +/* Check if there is an SD Card insterted into the SD Card socket. + */ + +#ifndef SD_RAW_IFACE +bool alt_up_sd_card_is_FAT16(void); +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + */ + + +short int alt_up_sd_card_fopen(char *name, bool create); +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + * + * Inputs: + * name - a file name including a directory, relative to the root directory + * create - a flag set to true to create a file if it does not already exist + * Output: + * An index to the file record assigned to the specified file. -1 is returned if the file could not be opened. + */ + + +short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name); +/* This function sets up a search algorithm to go through a given directory looking for files. + * If the search directory is valid, then the function searches for the first file it finds. + * Inputs: + * directory_to_search_through - name of the directory to search through + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * 0 - success + * 1 - invalid directory + * 2 - No card or incorrect card format. + * + * To specify a directory give the name in a format consistent with the following regular expression: + * [{[valid_chars]+}/]*. + * + * In other words, give a path name starting at the root directory, where each directory name is followed by a '/'. + * Then, append a '.' to the directory name. Examples: + * "." - look through the root directory + * "first/." - look through a directory named "first" that is located in the root directory. + * "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory. + * Invalid examples include: + * "/.", "/////." - this is not the root directory. + * "/first/." - the first character may not be a '/'. + */ + + + +short int alt_up_sd_card_find_next(char *file_name); +/* This function searches for the next file in a given directory, as specified by the find_first function. + * Inputs: + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * -1 - end of directory. + * 0 - success + * 2 - No card or incorrect card format. + * 4 - find_first has not been called successfully. + */ + +void alt_up_sd_card_set_attributes(short int file_handle, short int attributes); +/* Set file attributes as needed. + */ + +short int alt_up_sd_card_get_attributes(short int file_handle); +/* Return file attributes, or -1 if the file_handle is invalid. + */ + + +short int alt_up_sd_card_read(short int file_handle); +/* Read a single character from the given file. Return -1 if at the end of a file. Any other negative number + * means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */ + + +bool alt_up_sd_card_write(short int file_handle, char byte_of_data); +/* Write a single character to a given file. Return true if successful, and false otherwise. */ + + +bool alt_up_sd_card_fclose(short int file_handle); +// This function closes an opened file and saves data to SD Card if necessary. + +#else +bool Write_Sector_Data(int sector_index, int partition_offset); +bool Save_Modified_Sector(); +bool Read_Sector_Data(int sector_index, int partition_offset); +#endif //SD_RAW_IFACE + +////////////////////////////////////////////////////////////////////////// +// file-like operation functions + +////////////////////////////////////////////////////////////////////////// +// direct operation functions + + +/* + * Macros used by alt_sys_init + */ +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INSTANCE(name, device) \ + static alt_up_sd_card_dev device = \ + { \ + { \ + ALT_LLIST_ENTRY, \ + name##_NAME, \ + NULL , /* open */ \ + NULL , /* close */ \ + NULL, /* read */ \ + NULL, /* write */ \ + NULL , /* lseek */ \ + NULL , /* fstat */ \ + NULL , /* ioctl */ \ + }, \ + name##_BASE, \ + } + +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD_INIT(name, device) \ +{ \ + alt_dev_reg(&device.dev); \ +} + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALTERA_UP_SD_CARD_AVALON_INTERFACE_H__ */ + + diff --git a/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart.h b/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart.h new file mode 100644 index 0000000..95d4a99 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart.h @@ -0,0 +1,198 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALT_AVALON_JTAG_UART_H__ +#define __ALT_AVALON_JTAG_UART_H__ + +#include + +#include "sys/alt_alarm.h" +#include "sys/alt_warning.h" + +#include "os/alt_sem.h" +#include "os/alt_flag.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * If the user wants all drivers to be small rather than fast then make sure + * this one is marked as needing to be small. + */ +#if defined ALT_USE_SMALL_DRIVERS && !defined ALTERA_AVALON_JTAG_UART_SMALL +#define ALTERA_AVALON_JTAG_UART_SMALL +#endif + +/* + * If the user wants to ignore FIFO full error after timeout + */ +#if defined ALT_JTAG_UART_IGNORE_FIFO_FULL_ERROR && !defined ALTERA_AVALON_JTAG_UART_IGNORE_FIFO_FULL_ERROR +#define ALTERA_AVALON_JTAG_UART_IGNORE_FIFO_FULL_ERROR +#endif + +/* + * Constants that can be overriden. + */ +#ifndef ALTERA_AVALON_JTAG_UART_DEFAULT_TIMEOUT +#define ALTERA_AVALON_JTAG_UART_DEFAULT_TIMEOUT 10 +#endif + +#ifndef ALTERA_AVALON_JTAG_UART_BUF_LEN +#define ALTERA_AVALON_JTAG_UART_BUF_LEN 2048 +#endif + +/* + * ALT_JTAG_UART_READ_RDY and ALT_JTAG_UART_WRITE_RDY are the bitmasks + * that define uC/OS-II event flags that are releated to this device. + * + * ALT_JTAG_UART_READ_RDY indicates that there is read data in the buffer + * ready to be processed. ALT_JTAG_UART_WRITE_RDY indicates that the transmitter is + * ready for more data. + */ +#define ALT_JTAG_UART_READ_RDY 0x1 +#define ALT_JTAG_UART_WRITE_RDY 0x2 +#define ALT_JTAG_UART_TIMEOUT 0x4 + +/* + * State structure definition. Each instance of the driver uses one + * of these structures to hold its associated state. + */ + +typedef struct altera_avalon_jtag_uart_state_s +{ + unsigned int base; + +#ifndef ALTERA_AVALON_JTAG_UART_SMALL + + unsigned int timeout; /* Timeout until host is assumed inactive */ + alt_alarm alarm; + unsigned int irq_enable; + unsigned int host_inactive; + + ALT_SEM (read_lock) + ALT_SEM (write_lock) + ALT_FLAG_GRP (events) + + /* The variables below are volatile because they are modified by the + * interrupt routine. Making them volatile and reading them atomically + * means that we don't need any large critical sections. + */ + volatile unsigned int rx_in; + unsigned int rx_out; + unsigned int tx_in; + volatile unsigned int tx_out; + char rx_buf[ALTERA_AVALON_JTAG_UART_BUF_LEN]; + char tx_buf[ALTERA_AVALON_JTAG_UART_BUF_LEN]; + +#endif /* !ALTERA_AVALON_JTAG_UART_SMALL */ + +} altera_avalon_jtag_uart_state; + +/* + * Macros used by alt_sys_init when the ALT file descriptor facility isn't used. + */ + +#ifdef ALTERA_AVALON_JTAG_UART_SMALL + +#define ALTERA_AVALON_JTAG_UART_STATE_INSTANCE(name, state) \ + altera_avalon_jtag_uart_state state = \ + { \ + name##_BASE, \ + } + +#define ALTERA_AVALON_JTAG_UART_STATE_INIT(name, state) + +#else /* !ALTERA_AVALON_JTAG_UART_SMALL */ + +#define ALTERA_AVALON_JTAG_UART_STATE_INSTANCE(name, state) \ + altera_avalon_jtag_uart_state state = \ + { \ + name##_BASE, \ + ALTERA_AVALON_JTAG_UART_DEFAULT_TIMEOUT, \ + } + +/* + * Externally referenced routines + */ +extern void altera_avalon_jtag_uart_init(altera_avalon_jtag_uart_state* sp, + int irq_controller_id, int irq); + +#define ALTERA_AVALON_JTAG_UART_STATE_INIT(name, state) \ + { \ + if (name##_IRQ == ALT_IRQ_NOT_CONNECTED) \ + { \ + ALT_LINK_ERROR ("Error: Interrupt not connected for " #name ". " \ + "You have selected the interrupt driven version of " \ + "the ALTERA Avalon JTAG UART driver, but the " \ + "interrupt is not connected for this device. You can " \ + "select a polled mode driver by checking the 'small " \ + "driver' option in the HAL configuration window, or " \ + "by using the -DALTERA_AVALON_JTAG_UART_SMALL " \ + "preprocessor flag."); \ + } \ + else \ + altera_avalon_jtag_uart_init(&state, \ + name##_IRQ_INTERRUPT_CONTROLLER_ID, \ + name##_IRQ); \ + } + +#endif /* ALTERA_AVALON_JTAG_UART_SMALL */ + +/* + * Include in case non-direct version of driver required. + */ +#include "altera_avalon_jtag_uart_fd.h" + +/* + * Map alt_sys_init macros to direct or non-direct versions. + */ +#ifdef ALT_USE_DIRECT_DRIVERS + +#define ALTERA_AVALON_JTAG_UART_INSTANCE(name, state) \ + ALTERA_AVALON_JTAG_UART_STATE_INSTANCE(name, state) +#define ALTERA_AVALON_JTAG_UART_INIT(name, state) \ + ALTERA_AVALON_JTAG_UART_STATE_INIT(name, state) + +#else /* !ALT_USE_DIRECT_DRIVERS */ + +#define ALTERA_AVALON_JTAG_UART_INSTANCE(name, dev) \ + ALTERA_AVALON_JTAG_UART_DEV_INSTANCE(name, dev) +#define ALTERA_AVALON_JTAG_UART_INIT(name, dev) \ + ALTERA_AVALON_JTAG_UART_DEV_INIT(name, dev) + +#endif /* ALT_USE_DIRECT_DRIVERS */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_AVALON_JTAG_UART_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_fd.h b/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_fd.h new file mode 100644 index 0000000..b3c3200 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_fd.h @@ -0,0 +1,125 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALT_AVALON_JTAG_UART_FD_H__ +#define __ALT_AVALON_JTAG_UART_FD_H__ + +#include "sys/alt_dev.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Externally referenced routines + */ +extern int altera_avalon_jtag_uart_read_fd (alt_fd* fd, char* ptr, int len); +extern int altera_avalon_jtag_uart_write_fd (alt_fd* fd, const char* ptr, + int len); + +/* + * Device structure definition. This is needed by alt_sys_init in order to + * reserve memory for the device instance. + */ + +typedef struct altera_avalon_jtag_uart_dev_s +{ + alt_dev dev; + altera_avalon_jtag_uart_state state; +} altera_avalon_jtag_uart_dev; + +/* + * Macros used by alt_sys_init when the ALT file descriptor facility is used. + */ + +#ifdef ALTERA_AVALON_JTAG_UART_SMALL + +#define ALTERA_AVALON_JTAG_UART_DEV_INSTANCE(name, d) \ + static altera_avalon_jtag_uart_dev d = \ + { \ + { \ + ALT_LLIST_ENTRY, \ + name##_NAME, \ + NULL, /* open */ \ + NULL, /* close */ \ + altera_avalon_jtag_uart_read_fd, \ + altera_avalon_jtag_uart_write_fd, \ + NULL, /* lseek */ \ + NULL, /* fstat */ \ + NULL, /* ioctl */ \ + }, \ + { \ + name##_BASE, \ + } \ + } + +#define ALTERA_AVALON_JTAG_UART_DEV_INIT(name, d) alt_dev_reg (&d.dev) + +#else /* !ALTERA_AVALON_JTAG_UART_SMALL */ + +extern int altera_avalon_jtag_uart_close_fd(alt_fd* fd); +extern int altera_avalon_jtag_uart_ioctl_fd (alt_fd* fd, int req, void* arg); + +#define ALTERA_AVALON_JTAG_UART_DEV_INSTANCE(name, d) \ + static altera_avalon_jtag_uart_dev d = \ + { \ + { \ + ALT_LLIST_ENTRY, \ + name##_NAME, \ + NULL, /* open */ \ + altera_avalon_jtag_uart_close_fd, \ + altera_avalon_jtag_uart_read_fd, \ + altera_avalon_jtag_uart_write_fd, \ + NULL, /* lseek */ \ + NULL, /* fstat */ \ + altera_avalon_jtag_uart_ioctl_fd, \ + }, \ + { \ + name##_BASE, \ + ALTERA_AVALON_JTAG_UART_DEFAULT_TIMEOUT, \ + } \ + } + +#define ALTERA_AVALON_JTAG_UART_DEV_INIT(name, d) \ + { \ + ALTERA_AVALON_JTAG_UART_STATE_INIT(name, d.state); \ + \ + /* make the device available to the system */ \ + alt_dev_reg(&d.dev); \ + } + +#endif /* ALTERA_AVALON_JTAG_UART_SMALL */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_AVALON_JTAG_UART_FD_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_regs.h b/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_regs.h new file mode 100644 index 0000000..7f97160 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/altera_avalon_jtag_uart_regs.h @@ -0,0 +1,73 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALTERA_AVALON_JTAG_UART_REGS_H__ +#define __ALTERA_AVALON_JTAG_UART_REGS_H__ + +#include + +#define ALTERA_AVALON_JTAG_UART_DATA_REG 0 +#define IOADDR_ALTERA_AVALON_JTAG_UART_DATA(base) \ + __IO_CALC_ADDRESS_NATIVE(base, ALTERA_AVALON_JTAG_UART_DATA_REG) +#define IORD_ALTERA_AVALON_JTAG_UART_DATA(base) \ + IORD(base, ALTERA_AVALON_JTAG_UART_DATA_REG) +#define IOWR_ALTERA_AVALON_JTAG_UART_DATA(base, data) \ + IOWR(base, ALTERA_AVALON_JTAG_UART_DATA_REG, data) + +#define ALTERA_AVALON_JTAG_UART_DATA_DATA_MSK (0x000000FF) +#define ALTERA_AVALON_JTAG_UART_DATA_DATA_OFST (0) +#define ALTERA_AVALON_JTAG_UART_DATA_RVALID_MSK (0x00008000) +#define ALTERA_AVALON_JTAG_UART_DATA_RVALID_OFST (15) +#define ALTERA_AVALON_JTAG_UART_DATA_RAVAIL_MSK (0xFFFF0000) +#define ALTERA_AVALON_JTAG_UART_DATA_RAVAIL_OFST (16) + + +#define ALTERA_AVALON_JTAG_UART_CONTROL_REG 1 +#define IOADDR_ALTERA_AVALON_JTAG_UART_CONTROL(base) \ + __IO_CALC_ADDRESS_NATIVE(base, ALTERA_AVALON_JTAG_UART_CONTROL_REG) +#define IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base) \ + IORD(base, ALTERA_AVALON_JTAG_UART_CONTROL_REG) +#define IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(base, data) \ + IOWR(base, ALTERA_AVALON_JTAG_UART_CONTROL_REG, data) + +#define ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK (0x00000001) +#define ALTERA_AVALON_JTAG_UART_CONTROL_RE_OFST (0) +#define ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK (0x00000002) +#define ALTERA_AVALON_JTAG_UART_CONTROL_WE_OFST (1) +#define ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK (0x00000100) +#define ALTERA_AVALON_JTAG_UART_CONTROL_RI_OFST (8) +#define ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK (0x00000200) +#define ALTERA_AVALON_JTAG_UART_CONTROL_WI_OFST (9) +#define ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK (0x00000400) +#define ALTERA_AVALON_JTAG_UART_CONTROL_AC_OFST (10) +#define ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK (0xFFFF0000) +#define ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST (16) + +#endif /* __ALTERA_AVALON_JTAG_UART_REGS_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/altera_avalon_pio_regs.h b/software/sys_controller_bsp/drivers/inc/altera_avalon_pio_regs.h new file mode 100644 index 0000000..052439f --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/altera_avalon_pio_regs.h @@ -0,0 +1,67 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2003 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALTERA_AVALON_PIO_REGS_H__ +#define __ALTERA_AVALON_PIO_REGS_H__ + +#include + +#define IOADDR_ALTERA_AVALON_PIO_DATA(base) __IO_CALC_ADDRESS_NATIVE(base, 0) +#define IORD_ALTERA_AVALON_PIO_DATA(base) IORD(base, 0) +#define IOWR_ALTERA_AVALON_PIO_DATA(base, data) IOWR(base, 0, data) + +#define IOADDR_ALTERA_AVALON_PIO_DIRECTION(base) __IO_CALC_ADDRESS_NATIVE(base, 1) +#define IORD_ALTERA_AVALON_PIO_DIRECTION(base) IORD(base, 1) +#define IOWR_ALTERA_AVALON_PIO_DIRECTION(base, data) IOWR(base, 1, data) + +#define IOADDR_ALTERA_AVALON_PIO_IRQ_MASK(base) __IO_CALC_ADDRESS_NATIVE(base, 2) +#define IORD_ALTERA_AVALON_PIO_IRQ_MASK(base) IORD(base, 2) +#define IOWR_ALTERA_AVALON_PIO_IRQ_MASK(base, data) IOWR(base, 2, data) + +#define IOADDR_ALTERA_AVALON_PIO_EDGE_CAP(base) __IO_CALC_ADDRESS_NATIVE(base, 3) +#define IORD_ALTERA_AVALON_PIO_EDGE_CAP(base) IORD(base, 3) +#define IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base, data) IOWR(base, 3, data) + + +#define IOADDR_ALTERA_AVALON_PIO_SET_BIT(base) __IO_CALC_ADDRESS_NATIVE(base, 4) +#define IORD_ALTERA_AVALON_PIO_SET_BITS(base) IORD(base, 4) +#define IOWR_ALTERA_AVALON_PIO_SET_BITS(base, data) IOWR(base, 4, data) + +#define IOADDR_ALTERA_AVALON_PIO_CLEAR_BITS(base) __IO_CALC_ADDRESS_NATIVE(base, 5) +#define IORD_ALTERA_AVALON_PIO_CLEAR_BITS(base) IORD(base, 5) +#define IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(base, data) IOWR(base, 5, data) + + + +/* Defintions for direction-register operation with bi-directional PIOs */ +#define ALTERA_AVALON_PIO_DIRECTION_INPUT 0 +#define ALTERA_AVALON_PIO_DIRECTION_OUTPUT 1 + +#endif /* __ALTERA_AVALON_PIO_REGS_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod.h b/software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod.h new file mode 100644 index 0000000..2c58d09 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod.h @@ -0,0 +1,126 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALT_EPCQ_CONTROLLER_H__ +#define __ALT_EPCQ_CONTROLLER_H__ + +#include "alt_types.h" +#include "sys/alt_flash_dev.h" +#include "sys/alt_llist.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** + * Description of the EPCQ controller + */ +typedef struct alt_epcq_controller_dev +{ + alt_flash_dev dev; + + alt_u32 data_base; /** base address of data slave */ + alt_u32 data_end; /** end address of data slave (not inclusive) */ + alt_u32 csr_base; /** base address of CSR slave */ + alt_u32 size_in_bytes; /** size of memory in bytes */ + alt_u32 is_epcs; /** 1 if device is an EPCS device */ + alt_u32 number_of_sectors; /** number of flash sectors */ + alt_u32 sector_size; /** size of each flash sector */ + alt_u32 page_size; /** page size */ + alt_u32 silicon_id; /** ID of silicon used with EPCQ IP */ +} alt_epcq_controller_dev; + +/** +* Macros used by alt_sys_init.c to create data storage for driver instance +*/ +#define ALTERA_EPCQ_CONTROLLER_MOD_AVL_MEM_AVL_CSR_INSTANCE(epcq_name, avl_mem, avl_csr, epcq_dev) \ +alt_epcq_controller_dev epcq_dev = \ +{ \ + .dev = { \ + .llist = ALT_LLIST_ENTRY, \ + .name = avl_mem##_NAME, \ + .write = alt_epcq_controller_write, \ + .read = alt_epcq_controller_read, \ + .get_info = alt_epcq_controller_get_info, \ + .erase_block = alt_epcq_controller_erase_block, \ + .write_block = alt_epcq_controller_write_block, \ + .base_addr = ((void*)(avl_mem##_BASE)), \ + .length = ((int)(avl_mem##_SPAN)), \ + .lock = alt_epcq_controller_lock , \ + }, \ + .data_base = ((alt_u32)(avl_mem##_BASE)), \ + .data_end = ((alt_u32)(avl_mem##_BASE) + (alt_u32)(avl_mem##_SPAN)), \ + .csr_base = ((alt_u32)(avl_csr##_BASE)), \ + .size_in_bytes = ((alt_u32)(avl_mem##_SPAN)), \ + .is_epcs = ((alt_u32)(avl_mem##_IS_EPCS)), \ + .number_of_sectors = ((alt_u32)(avl_mem##_NUMBER_OF_SECTORS)), \ + .sector_size = ((alt_u32)(avl_mem##_SECTOR_SIZE)), \ + .page_size = ((alt_u32)(avl_mem##_PAGE_SIZE)) , \ +} + +/* + Public API + + Refer to Using Flash Devices in the + Developing Programs Using the Hardware Abstraction Layer chapter + of the Nios II Software Developer's Handbook. + +*/ +int alt_epcq_controller_read(alt_flash_dev *flash_info, int offset, void *dest_addr, int length); + +int alt_epcq_controller_get_info(alt_flash_fd *fd, flash_region **info, int *number_of_regions); + +int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset); + +int alt_epcq_controller_write_block(alt_flash_dev *flash_info, int block_offset, int data_offset, const void *data, int length); + +int alt_epcq_controller_write(alt_flash_dev *flash_info, int offset, const void *src_addr, int length); + +int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock); + + +/* + * Initialization function + */ +extern alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *dev); + +/* + * alt_sys_init.c will call this macro automatically initialize the driver instance + */ +#define ALTERA_EPCQ_CONTROLLER_MOD_INIT(name, dev) \ + altera_epcq_controller_init(&dev); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_EPCQ_CONTROLLER_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod_regs.h b/software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod_regs.h new file mode 100644 index 0000000..3d36697 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/altera_epcq_controller_mod_regs.h @@ -0,0 +1,260 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2014 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#ifndef __ALTERA_EPCQ_CONTROLLER_REGS_H__ +#define __ALTERA_EPCQ_CONTROLLER_REGS_H__ + +#include + +/* + * EPCQ_RD_STATUS register offset + * + * The EPCQ_RD_STATUS register contains information from the read status + * register operation. A full description of the register can be found in the + * data sheet, + * + */ +#define ALTERA_EPCQ_CONTROLLER_STATUS_REG (0x0) + +/* + * EPCQ_RD_STATUS register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_STATUS(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_STATUS(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_STATUS(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_STATUS_REG, data) + +/* + * EPCQ_RD_STATUS register description macros + */ + +/** Write in progress bit */ +#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_AVAILABLE (0x00000000) +#define ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY (0x00000001) +/** When to time out a poll of the write in progress bit */ +/* 0.7 sec time out */ +#define ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE 700000 + +/* + * EPCQ_RD_SID register offset + * + * The EPCQ_RD_SID register contains the information from the read silicon ID + * operation and can be used to determine what type of EPCS device we have. + * Only support in EPCS16 and EPCS64. + * + * This register is valid only if the device is an EPCS. + * + */ +#define ALTERA_EPCQ_CONTROLLER_SID_REG (0x4) + +/* + * EPCQ_RD_SID register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_SID(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_SID_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_SID(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_SID_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_SID(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_SID_REG, data) + +/* + * EPCQ_RD_SID register description macros + * + * Specific device values obtained from Table 14 of: + * "Serial Configuration (EPCS) Devices Datasheet" + */ +#define ALTERA_EPCQ_CONTROLLER_SID_MASK (0x000000FF) +#define ALTERA_EPCQ_CONTROLLER_SID_EPCS16 (0x00000014) +#define ALTERA_EPCQ_CONTROLLER_SID_EPCS64 (0x00000016) +#define ALTERA_EPCQ_CONTROLLER_SID_EPCS128 (0x00000018) + +/* + * EPCQ_RD_RDID register offset + * + * The EPCQ_RD_RDID register contains the information from the read memory + * capacity operation and can be used to determine what type of EPCQ device + * we have. + * + * This register is only valid if the device is an EPCQ. + * + */ +#define ALTERA_EPCQ_CONTROLLER_RDID_REG (0x8) + +/* + * EPCQ_RD_RDID register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_RDID(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_RDID_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_RDID(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_RDID_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_RDID(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_RDID_REG, data) + +/* + * EPCQ_RD_RDID register description macros + * + * Specific device values obtained from Table 28 of: + * "Quad-Serial Configuration (EPCQ (www.altera.com/literature/hb/cfg/cfg_cf52012.pdf)) + * Devices Datasheet" + */ +#define ALTERA_EPCQ_CONTROLLER_RDID_MASK (0x000000FF) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16 (0x00000015) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32 (0x00000016) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64 (0x00000017) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128 (0x00000018) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256 (0x00000019) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512 (0x00000020) +#define ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024 (0x00000021) + +/* + * EPCQ_MEM_OP register offset + * + * The EPCQ_MEM_OP register is used to do memory protect and erase operations + * + */ +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_REG (0xC) + +/* + * EPCQ_MEM_OP register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_MEM_OP(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_MEM_OP(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_MEM_OP_REG, data) + +/* + * EPCQ_MEM_OP register description macros + */ +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_CMD_MASK (0x00000003) +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_BULK_ERASE_CMD (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD (0x00000002) +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD (0x00000003) + +/** see datasheet for sector values */ +#define ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK (0x00FFFF00) + +/* + * EPCQ_ISR register offset + * + * The EPCQ_ISR register is used to determine whether an invalid write or erase + * operation triggered an interrupt + * + */ +#define ALTERA_EPCQ_CONTROLLER_ISR_REG (0x10) + +/* + * EPCQ_ISR register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_ISR(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_ISR_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_ISR(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_ISR_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_ISR(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_ISR_REG, data) + +/* + * EPCQ_ISR register description macros + */ +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE (0x00000001) + +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK (0x00000002) +#define ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE (0x00000002) + + +/* + * EPCQ_IMR register offset + * + * The EPCQ_IMR register is used to mask the invalid erase or the invalid write + * interrupts. + * + */ +#define ALTERA_EPCQ_CONTROLLER_IMR_REG (0x14) + +/* + * EPCQ_IMR register access macros + */ +#define IOADDR_ALTERA_EPCQ_CONTROLLER_IMR(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CONTROLLER_IMR_REG) + +#define IORD_ALTERA_EPCQ_CONTROLLER_IMR(base) \ + IORD_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_IMR_REG) + +#define IOWR_ALTERA_EPCQ_CONTROLLER_IMR(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CONTROLLER_IMR_REG, data) + +/* + * EPCQ_IMR register description macros + */ +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_ERASE_MASK (0x00000001) +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_ERASE_ENABLED (0x00000001) + +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_WRITE_MASK (0x00000002) +#define ALTERA_EPCQ_CONTROLLER_IMR_ILLEGAL_WRITE_ENABLED (0x00000002) + +/* + * EPCQ_CHIP_SELECT register offset + * + * The EPCQ_CHIP_SELECT register is used to issue chip select + */ +#define ALTERA_EPCQ_CHIP_SELECT_REG (0x18) + +/* + * EPCQ_CHIP_SELECT register access macros + */ +#define IOADDR_ALTERA_EPCQ_CHIP_SELECT(base) \ + __IO_CALC_ADDRESS_DYNAMIC(base, ALTERA_EPCQ_CHIP_SELECT_REG) + +#define IOWR_ALTERA_EPCQ_CHIP_SELECT(base, data) \ + IOWR_32DIRECT(base, ALTERA_EPCQ_CHIP_SELECT_REG, data) + +/* + * EPCQ_CHIP_SELECT register description macros + */ +#define ALTERA_EPCQ_CHIP1_SELECT (0x00000001) +#define ALTERA_EPCQ_CHIP2_SELECT (0x00000002) +#define ALTERA_EPCQ_CHIP3_SELECT (0x00000003) + +#endif /* __ALTERA_EPCQ_CONTROLLER_REGS_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/ci_crc.h b/software/sys_controller_bsp/drivers/inc/ci_crc.h new file mode 100644 index 0000000..ba4d983 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/ci_crc.h @@ -0,0 +1,38 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +#ifndef _CRCCI_H_ +#define _CRCCI_H_ + +unsigned long crcCI(unsigned char * input_data, unsigned long input_data_length, int do_initialize); + +#endif //_CRCCI_H_ diff --git a/software/sys_controller_bsp/drivers/inc/crc.h b/software/sys_controller_bsp/drivers/inc/crc.h new file mode 100644 index 0000000..4db516e --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/crc.h @@ -0,0 +1,109 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/********************************************************************** + * + * Filename: crc.h + * + * Description: A header file describing the various CRC standards. + * + * Notes: + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#ifndef _crc_h +#define _crc_h + + +#define FALSE 0 +#define TRUE !FALSE + +/* + * Select the CRC standard from the list that follows. + */ +#define CRC32 + + +#if defined(CRC_CCITT) + +typedef unsigned short crc; + +#define CRC_NAME "CRC-CCITT" +#define POLYNOMIAL 0x1021 +#define INITIAL_REMAINDER 0xFFFF +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA FALSE +#define REFLECT_REMAINDER FALSE +#define CHECK_VALUE 0x29B1 + +#elif defined(CRC16) + +typedef unsigned short crc; + +#define CRC_NAME "CRC-16" +#define POLYNOMIAL 0x8005 +#define INITIAL_REMAINDER 0x0000 +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xBB3D + +#elif defined(CRC32) + +typedef unsigned long crc; + +#define CRC_NAME "CRC-32" +#define POLYNOMIAL 0x04C11DB7 +#define INITIAL_REMAINDER 0xFFFFFFFF +#define FINAL_XOR_VALUE 0xFFFFFFFF +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xCBF43926 + +#else + +#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd." + +#endif + + +void crcInit(void); +crc crcSlow(unsigned char const message[], int nBytes); +crc crcFast(unsigned char const message[], int nBytes); + + +#endif /* _crc_h */ diff --git a/software/sys_controller_bsp/drivers/inc/i2c_opencores.h b/software/sys_controller_bsp/drivers/inc/i2c_opencores.h new file mode 100644 index 0000000..c772b67 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/i2c_opencores.h @@ -0,0 +1,33 @@ +#ifndef __I2C_OPENCORES_H__ +#define __I2C_OPENCORES_H__ + + +#include "alt_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + + + +void I2C_init(alt_u32 base,alt_u32 clk,alt_u32 speed); +int I2C_start(alt_u32 base, alt_u32 add, alt_u32 read); +alt_u32 I2C_read(alt_u32 base,alt_u32 last); +alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last); +alt_u32 SPI_read(alt_u32 base); +void SPI_write(alt_u32 base,alt_u8 data); +#define I2C_OK (0) +#define I2C_ACK (0) +#define I2C_NOACK (1) +#define I2C_ABITRATION_LOST (2) + +#define I2C_OPENCORES_INSTANCE(name, dev) extern int alt_no_storage +#define I2C_OPENCORES_INIT(name, dev) while (0) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __I2C_OPENCORES_H__ */ diff --git a/software/sys_controller_bsp/drivers/inc/i2c_opencores_regs.h b/software/sys_controller_bsp/drivers/inc/i2c_opencores_regs.h new file mode 100644 index 0000000..17f79c3 --- /dev/null +++ b/software/sys_controller_bsp/drivers/inc/i2c_opencores_regs.h @@ -0,0 +1,77 @@ + + +#ifndef __I2C_OPENCORES_REGS_H__ +#define __I2C_OPENCORES_REGS_H__ + +#include +/* prescal clock/(5*desired_SCL) */ +/* all registers are 8 bits wide but on 32 bit address boundaries.*/ +/* reg definitions take from i2c_specs.pdf in the docs folder */ + +#define IOADDR_I2C_OPENCORES_PRERLO(base) __IO_CALC_ADDRESS_NATIVE(base, 0) +#define IORD_I2C_OPENCORES_PRERLO(base) IORD(base, 0) +#define IOWR_I2C_OPENCORES_PRERLO(base, data) IOWR(base, 0, data) + + +#define IOADDR_I2C_OPENCORES_PRERHI(base) __IO_CALC_ADDRESS_NATIVE(base, 0) +#define IORD_I2C_OPENCORES_PRERHI(base) IORD(base, 1) +#define IOWR_I2C_OPENCORES_PRERHI(base, data) IOWR(base, 1, data) + + +#define IOADDR_I2C_OPENCORES_CTR(base) __IO_CALC_ADDRESS_NATIVE(base, 2) +#define IORD_I2C_OPENCORES_CTR(base) IORD(base, 2) +#define IOWR_I2C_OPENCORES_CTR(base, data) IOWR(base, 2, data) +/* bit definitions*/ +#define I2C_OPENCORES_CTR_EN_MSK (0x80) +#define I2C_OPENCORES_CTR_EN_OFST (7) +#define I2C_OPENCORES_CTR_IEN_MSK (0x40) +#define I2C_OPENCORES_CTR_IEN_OFST (6) + + +#define IOADDR_I2C_OPENCORES_TXR(base) __IO_CALC_ADDRESS_NATIVE(base, 3) +#define IOWR_I2C_OPENCORES_TXR(base, data) IOWR(base, 3, data) +/* bit definitions*/ +#define I2C_OPENCORES_TXR_RD_MSK (0x1) +#define I2C_OPENCORES_TXR_RD_OFST (0) +#define I2C_OPENCORES_TXR_WR_MSK (0x0) +#define I2C_OPENCORES_TXR_WR_OFST (0) + + +#define IOADDR_I2C_OPENCORES_RXR(base) __IO_CALC_ADDRESS_NATIVE(base, 3) +#define IORD_I2C_OPENCORES_RXR(base) IORD(base, 3) + + +#define IOADDR_I2C_OPENCORES_CR(base) __IO_CALC_ADDRESS_NATIVE(base, 4) +#define IOWR_I2C_OPENCORES_CR(base, data) IOWR(base, 4, data) +/* bit definitions*/ +#define I2C_OPENCORES_CR_STA_MSK (0x80) +#define I2C_OPENCORES_CR_STA_OFST (7) +#define I2C_OPENCORES_CR_STO_MSK (0x40) +#define I2C_OPENCORES_CR_STO_OFST (6) +#define I2C_OPENCORES_CR_RD_MSK (0x20) +#define I2C_OPENCORES_CR_RD_OFST (5) +#define I2C_OPENCORES_CR_WR_MSK (0x10) +#define I2C_OPENCORES_CR_WR_OFST (4) +#define I2C_OPENCORES_CR_NACK_MSK (0x8) +#define I2C_OPENCORES_CR_NACK_OFST (3) +#define I2C_OPENCORES_CR_SPIM_MSK (0x4) +#define I2C_OPENCORES_CR_SPIM_OFST (2) +#define I2C_OPENCORES_CR_IACK_MSK (0x1) +#define I2C_OPENCORES_CR_IACK_OFST (0) + + +#define IOADDR_I2C_OPENCORES_SR(base) __IO_CALC_ADDRESS_NATIVE(base, 4) +#define IORD_I2C_OPENCORES_SR(base) IORD(base, 4) +/* bit definitions*/ +#define I2C_OPENCORES_SR_RXNACK_MSK (0x80) +#define I2C_OPENCORES_SR_RXNACK_OFST (7) +#define I2C_OPENCORES_SR_BUSY_MSK (0x40) +#define I2C_OPENCORES_SR_BUSY_OFST (6) +#define I2C_OPENCORES_SR_AL_MSK (0x20) +#define I2C_OPENCORES_SR_AL_OFST (5) +#define I2C_OPENCORES_SR_TIP_MSK (0x2) +#define I2C_OPENCORES_SR_TIP_OFST (1) +#define I2C_OPENCORES_SR_IF_MSK (0x1) +#define I2C_OPENCORES_SR_IF_OFST (0) + +#endif /* __I2C_OPENCORES_REGS_H__ */ diff --git a/software/sys_controller_bsp/drivers/src/Altera_UP_SD_Card_Avalon_Interface_mod.c b/software/sys_controller_bsp/drivers/src/Altera_UP_SD_Card_Avalon_Interface_mod.c new file mode 100644 index 0000000..b98e077 --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/Altera_UP_SD_Card_Avalon_Interface_mod.c @@ -0,0 +1,1908 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include +#include +#include "Altera_UP_SD_Card_Avalon_Interface_mod.h" + +/////////////////////////////////////////////////////////////////////////// +// Local Define Statements +/////////////////////////////////////////////////////////////////////////// + +#define CHAR_TO_UPPER(ch) ((char) (((ch >= 'a') && (ch <= 'z')) ? ((ch-'a')+'A'): ch)) + +// Data Buffer Address +#define SD_CARD_BUFFER(base, x) (base + x) +// 128-bit Card Identification Number +#define SD_CARD_CID(base, x) (base + 0x0200 + x) +// 128-bit Card Specific Data Register +#define SD_CARD_CSD(base, x) (base + 0x0210 + x) +// 32-bit Operating Conditions Register +#define SD_CARD_OCR(base) (base + 0x0220) +// 32-bit Card Status Register +#define SD_CARD_STATUS(base) (base + 0x0224) +// 16-bit Relative Card Address Register +#define SD_CARD_RCA(base) (base + 0x0228) +// 32-bit Card Argument Register +#define SD_CARD_ARGUMENT(base) (base + 0x022C) +// 16-bit Card Command Register +#define SD_CARD_COMMAND(base) (base + 0x0230) +// 16-bit Card Auxiliary Status Register +#define SD_CARD_AUX_STATUS(base) (base + 0x0234) +// 32-bit R1 Response Register +#define SD_CARD_R1_RESPONSE(base) (base + 0x0238) + +#define CMD_READ_BLOCK 17 +#define CMD_WRITE_BLOCK 24 + +// FAT 12/16 related stuff +//#define BOOT_SECTOR_DATA_SIZE 0x005A +#define MAX_FILES_OPENED 2 + +/******************************************************************************/ +/****** LOCAL DATA STRUCTURES ***********************************************/ +/******************************************************************************/ + + +typedef struct s_FAT_12_16_boot_sector { + unsigned char jump_instruction[3]; + char OEM_name[8]; + unsigned short int sector_size_in_bytes; + unsigned char sectors_per_cluster; + unsigned short int reserved_sectors; + unsigned char number_of_FATs; + unsigned short int max_number_of_dir_entires; + unsigned short int number_of_sectors_in_partition; + unsigned char media_descriptor; + unsigned short int number_of_sectors_per_table; + unsigned short int number_of_sectors_per_track; + unsigned short int number_of_heads; + unsigned int number_of_hidden_sectors; + unsigned int total_sector_count_if_above_32MB; + unsigned char drive_number; + unsigned char current_head; + unsigned char boot_signature; + unsigned char volume_id[4]; + char volume_label[11]; + unsigned char file_system_type[8]; + unsigned char bits_for_cluster_index; + unsigned int first_fat_sector_offset; + unsigned int second_fat_sector_offset; + unsigned int root_directory_sector_offset; + unsigned int data_sector_offset; +} t_FAT_12_16_boot_sector; + + +typedef struct s_file_record { + unsigned char name[8]; + unsigned char extension[3]; + unsigned char attributes; + unsigned short int create_time; + unsigned short int create_date; + unsigned short int last_access_date; + unsigned short int last_modified_time; + unsigned short int last_modified_date; + unsigned short int start_cluster_index; + unsigned int file_size_in_bytes; + /* The following fields are only used when a file has been created or opened. */ + unsigned int current_cluster_index; + unsigned int current_sector_in_cluster; + unsigned int current_byte_position; + // Absolute location of the file record on the SD Card. + unsigned int file_record_cluster; + unsigned int file_record_sector_in_cluster; + short int file_record_offset; + // Is this record in use and has the file been modified. + unsigned int home_directory_cluster; + bool modified; + bool in_use; +} t_file_record; + + +typedef struct s_find_data { + unsigned int directory_root_cluster; // 0 means root directory. + unsigned int current_cluster_index; + unsigned int current_sector_in_cluster; + short int file_index_in_sector; + bool valid; +} t_find_data; + + +/////////////////////////////////////////////////////////////////////////// +// Local Variables +/////////////////////////////////////////////////////////////////////////// + + +bool initialized = false; +bool is_sd_card_formated_as_FAT16 = false; +volatile short int *aux_status_register = NULL; +volatile int *status_register = NULL; +volatile short int *CSD_register_w0 = NULL; +volatile short int *command_register = NULL; +volatile int *command_argument_register = NULL; +volatile char *buffer_memory = NULL; +int fat_partition_offset_in_512_byte_sectors = 0; +int fat_partition_size_in_512_byte_sectors = 0; + +#ifndef SD_RAW_IFACE +t_FAT_12_16_boot_sector boot_sector_data; +#endif + +alt_up_sd_card_dev *device_pointer = NULL; + +#ifndef SD_RAW_IFACE +// Pointers to currently opened files. +t_file_record active_files[MAX_FILES_OPENED]; +#endif +bool current_sector_modified = false; +unsigned int current_sector_index = 0; + +#ifndef SD_RAW_IFACE +t_find_data search_data; +#endif + + +/////////////////////////////////////////////////////////////////////////// +// Local Functions +/////////////////////////////////////////////////////////////////////////// + +#ifndef SD_RAW_IFACE +static bool Write_Sector_Data(int sector_index, int partition_offset) +#else +bool Write_Sector_Data(int sector_index, int partition_offset) +#endif +// This function writes a sector at the specified address on the SD Card. +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + short int reg_state = 0xff; + + /* Multiply sector offset by sector size to get the address. Sector size is 512. Also, + * the SD card reads data in 512 byte chunks, so the address must be a multiple of 512. */ + IOWR_32DIRECT(command_argument_register, 0, (sector_index + partition_offset)*512); + IOWR_16DIRECT(command_register, 0, CMD_WRITE_BLOCK); + do { + reg_state = (short int) IORD_16DIRECT(aux_status_register,0); + } while ((reg_state & 0x04)!=0); + // Make sure the request did not time out. + if ((reg_state & 0x10) == 0) + { + result = true; + current_sector_modified = false; + current_sector_index = sector_index+partition_offset; + } + } + return result; +} + +#ifndef SD_RAW_IFACE +static bool Save_Modified_Sector() +#else +bool Save_Modified_Sector() +#endif +// If the sector has been modified, then save it to the SD Card. +{ + bool result = true; + if (current_sector_modified) + { + result = Write_Sector_Data(current_sector_index, 0); + } + return result; +} + +#ifndef SD_RAW_IFACE +static bool Read_Sector_Data(int sector_index, int partition_offset) +#else +bool Read_Sector_Data(int sector_index, int partition_offset) +#endif +// This function reads a sector at the specified address on the SD Card. +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + short int reg_state = 0xff; + + /* Write data to the SD card if the current buffer is out of date. */ + if (current_sector_modified) + { + if (Write_Sector_Data(current_sector_index, 0) == false) + { + return false; + } + } + /* Multiply sector offset by sector size to get the address. Sector size is 512. Also, + * the SD card reads data in 512 byte chunks, so the address must be a multiple of 512. */ + IOWR_32DIRECT(command_argument_register, 0, (sector_index + partition_offset)*512); + IOWR_16DIRECT(command_register, 0, CMD_READ_BLOCK); + do { + reg_state = (short int) IORD_16DIRECT(aux_status_register,0); + } while ((reg_state & 0x04)!=0); + // Make sure the request did not time out. + if ((reg_state & 0x10) == 0) + { + result = true; + current_sector_modified = false; + current_sector_index = sector_index+partition_offset; + } + } + return result; +} + +#ifndef SD_RAW_IFACE +static bool get_cluster_flag(unsigned int cluster_index, unsigned short int *flag) +// Read a cluster flag. +{ + unsigned int sector_index = (cluster_index / 256) + fat_partition_offset_in_512_byte_sectors; + + sector_index = sector_index + boot_sector_data.first_fat_sector_offset; + + if (sector_index != current_sector_index) + { + if (Read_Sector_Data(sector_index, 0) == false) + { + return false; + } + } + *flag = (unsigned short int) IORD_16DIRECT(device_pointer->base, 2*(cluster_index % 256)); + return true; +} + + +static bool mark_cluster(unsigned int cluster_index, short int flag, bool first_fat) +// Place a marker on the specified cluster in a given FAT. +{ + unsigned int sector_index = (cluster_index / 256) + fat_partition_offset_in_512_byte_sectors; + + if (first_fat) + { + sector_index = sector_index + boot_sector_data.first_fat_sector_offset; + } + else + { + sector_index = sector_index + boot_sector_data.second_fat_sector_offset; + } + + if (sector_index != current_sector_index) + { + if (Read_Sector_Data(sector_index, 0) == false) + { + return false; + } + } + IOWR_16DIRECT(device_pointer->base, 2*(cluster_index % 256), flag); + current_sector_modified = true; + return true; +} + + +static bool Check_for_Master_Boot_Record(void) +// This function reads the first 512 bytes on the SD Card. This data should +// contain the Master Boot Record. If it does, then print +// relevant information and return true. Otherwise, return false. +{ + bool result = false; + int index; + int end, offset, partition_size; + + /* Load the first 512 bytes of data from SD card. */ + if (Read_Sector_Data(0, 0)) + { + end = (short int) IORD_16DIRECT(device_pointer->base,0x1fe); + + // Check if the end of the sector contains an end string 0xaa55. + if ((end & 0x0000ffff) == 0x0000aa55) + { + // Check four partition entries and see if any are valid + for (index = 0; index < 4; index++) + { + int partition_data_offset = (index * 16) + 0x01be; + char type; + + // Read Partition type + type = (unsigned char) IORD_8DIRECT(device_pointer->base,partition_data_offset + 0x04); + + // Check if this is an FAT parition + if ((type == 1) || (type == 4) || (type == 6) || (type == 14)) + { + // Get partition offset and size. + offset = (((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0A)) << 16) | ((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x08)); + partition_size = (((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0E)) << 16) | ((unsigned short int) IORD_16DIRECT(device_pointer->base,partition_data_offset + 0x0C)); + + // Check if the partition is valid + if (partition_size > 0) + { + result = true; + fat_partition_size_in_512_byte_sectors = partition_size; + fat_partition_offset_in_512_byte_sectors = offset; + break; + } + } + } + } + } + + return result; +} + + +static bool Read_File_Record_At_Offset(int offset, t_file_record *record, unsigned int cluster_index, unsigned int sector_in_cluster) +// This function reads a file record +{ + bool result = false; + if (((offset & 0x01f) == 0) && (alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + int counter; + + for (counter = 0; counter < 8; counter++) + { + record->name[counter] = (char) IORD_8DIRECT(device_pointer->base, offset+counter); + } + for (counter = 0; counter < 3; counter++) + { + record->extension[counter] = (char) IORD_8DIRECT(device_pointer->base, offset+counter+8); + } + record->attributes = (char) IORD_8DIRECT(device_pointer->base, offset+11); + /* Ignore reserved bytes at locations 12 and 13. */ + record->create_time = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+14); + record->create_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+16); + record->last_access_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+18); + /* Ignore reserved bytes at locations 20 and 21. */ + record->last_modified_time = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+22); + record->last_modified_date = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+24); + record->start_cluster_index = (unsigned short int) IORD_16DIRECT(device_pointer->base, offset+26); + record->file_size_in_bytes = (unsigned int) IORD_32DIRECT(device_pointer->base, offset+28); + record->file_record_cluster = cluster_index; + record->file_record_sector_in_cluster = sector_in_cluster; + record->file_record_offset = offset; + result = true; + } + return result; +} + + +static bool Write_File_Record_At_Offset(int offset, t_file_record *record) +// This function writes a file record at a given offset. The offset is given in bytes. +{ + bool result = false; + if (((offset & 0x01f) == 0) && (alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + int counter; + + for (counter = 0; counter < 8; counter=counter+2) + { + short int two_chars = (short int) record->name[counter+1]; + two_chars = two_chars << 8; + two_chars = two_chars | record->name[counter]; + IOWR_16DIRECT(device_pointer->base, offset+counter, two_chars); + } + for (counter = 0; counter < 3; counter++) + { + IOWR_8DIRECT(device_pointer->base, offset+counter+8, record->extension[counter]); + } + IOWR_8DIRECT(device_pointer->base, offset+11, record->attributes); + /* Ignore reserved bytes at locations 12 and 13. */ + IOWR_16DIRECT(device_pointer->base, offset+14, record->create_time); + IOWR_16DIRECT(device_pointer->base, offset+16, record->create_date); + IOWR_16DIRECT(device_pointer->base, offset+18, record->last_access_date); + /* Ignore reserved bytes at locations 20 and 21. */ + IOWR_16DIRECT(device_pointer->base, offset+22, record->last_modified_time); + IOWR_16DIRECT(device_pointer->base, offset+24, record->last_modified_date); + IOWR_16DIRECT(device_pointer->base, offset+26, record->start_cluster_index); + IOWR_32DIRECT(device_pointer->base, offset+28, record->file_size_in_bytes); + current_sector_modified = true; + result = true; + } + return result; +} + + +static bool Check_for_DOS_FAT(int FAT_partition_start_sector) +// This function reads the boot sector for the FAT file system on the SD Card. +// The offset_address should point to the sector on the card where the boot sector is located. +// The sector number is specified either in the master Boot Record, or is 0 by default for a purely FAT +// based file system. If the specified sector contains a FAT boot sector, then this function prints the +// relevant information and returns 1. Otherwise, it returns 0. +{ + bool result = false; + int counter = 0; + short int end; + + result = Read_Sector_Data(0, FAT_partition_start_sector); + end = (short int) IORD_16DIRECT(device_pointer->base, 0x1fe); + if (((end & 0x0000ffff) == 0x0000aa55) && (result)) + { + int num_clusters = 0; + + boot_sector_data.jump_instruction[0] = (char) IORD_8DIRECT(device_pointer->base, 0); + boot_sector_data.jump_instruction[1] = (char) IORD_8DIRECT(device_pointer->base, 1); + boot_sector_data.jump_instruction[2] = (char) IORD_8DIRECT(device_pointer->base, 2); + for (counter = 0; counter < 8; counter++) + { + boot_sector_data.OEM_name[counter] = (char) IORD_8DIRECT(device_pointer->base, 3+counter); + } + boot_sector_data.sector_size_in_bytes = (((unsigned char) IORD_8DIRECT(device_pointer->base, 12)) << 8 ) | ((char) IORD_8DIRECT(device_pointer->base, 11)); + boot_sector_data.sectors_per_cluster = ((unsigned char) IORD_8DIRECT(device_pointer->base, 13)); + boot_sector_data.reserved_sectors = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 14)); + boot_sector_data.number_of_FATs = ((unsigned char) IORD_8DIRECT(device_pointer->base, 16)); + boot_sector_data.max_number_of_dir_entires = (((unsigned short int)(((unsigned char) IORD_8DIRECT(device_pointer->base, 18)))) << 8 ) | ((unsigned char) IORD_8DIRECT(device_pointer->base, 17)); + boot_sector_data.number_of_sectors_in_partition = (((unsigned short int)(((unsigned char) IORD_8DIRECT(device_pointer->base, 20)))) << 8 ) | ((unsigned char) IORD_8DIRECT(device_pointer->base, 19)); + boot_sector_data.media_descriptor = ((unsigned char) IORD_8DIRECT(device_pointer->base, 21)); + boot_sector_data.number_of_sectors_per_table = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 22)); + boot_sector_data.number_of_sectors_per_track = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 24)); + boot_sector_data.number_of_heads = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 26)); + boot_sector_data.number_of_hidden_sectors = ((unsigned int) IORD_32DIRECT(device_pointer->base, 28)); + boot_sector_data.total_sector_count_if_above_32MB = ((unsigned int) IORD_32DIRECT(device_pointer->base, 32)); + boot_sector_data.drive_number = ((unsigned char) IORD_8DIRECT(device_pointer->base, 36)); + boot_sector_data.current_head = ((unsigned char) IORD_8DIRECT(device_pointer->base, 37)); + boot_sector_data.boot_signature = ((unsigned char) IORD_8DIRECT(device_pointer->base, 38)); + boot_sector_data.first_fat_sector_offset = boot_sector_data.reserved_sectors; + boot_sector_data.second_fat_sector_offset = boot_sector_data.first_fat_sector_offset + boot_sector_data.number_of_sectors_per_table; + boot_sector_data.root_directory_sector_offset = boot_sector_data.second_fat_sector_offset + boot_sector_data.number_of_sectors_per_table; + boot_sector_data.data_sector_offset = boot_sector_data.root_directory_sector_offset + (32*boot_sector_data.max_number_of_dir_entires / boot_sector_data.sector_size_in_bytes); + + if (boot_sector_data.number_of_sectors_in_partition > 0) + { + num_clusters = (boot_sector_data.number_of_sectors_in_partition / boot_sector_data.sectors_per_cluster); + } + else + { + num_clusters = (boot_sector_data.total_sector_count_if_above_32MB / boot_sector_data.sectors_per_cluster); + } + if (num_clusters < 4087) + { + boot_sector_data.bits_for_cluster_index = 12; + } + else if (num_clusters <= 65517) + { + boot_sector_data.bits_for_cluster_index = 16; + } + else + { + boot_sector_data.bits_for_cluster_index = 32; + } + + for (counter = 0; counter < 4; counter++) + { + boot_sector_data.volume_id[counter] = ((char) IORD_8DIRECT(device_pointer->base, 39+counter)); + } + for (counter = 0; counter < 11; counter++) + { + boot_sector_data.volume_label[counter] = ((char) IORD_8DIRECT(device_pointer->base, 43+counter)); + } + for (counter = 0; counter < 8; counter++) + { + boot_sector_data.file_system_type[counter] = ((char) IORD_8DIRECT(device_pointer->base, 54+counter)); + } + // Clear file records + for (counter = 0; counter < MAX_FILES_OPENED; counter++) + { + active_files[counter].in_use = false; + } + result = true; + } + else + { + result = false; + } + return result; +} + + +static bool Look_for_FAT16(void) +// Read the SD card to determine if it contains a FAT16 partition. +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + short int csd_file_format = *CSD_register_w0; + + fat_partition_offset_in_512_byte_sectors = 0; + fat_partition_size_in_512_byte_sectors = 0; + + if (((csd_file_format & 0x8000) == 0) && ((csd_file_format & 0x0c00) != 0x0c00)) + { + if ((csd_file_format & 0x0c00) == 0x0400) + { + /* SD Card contains files stored in a DOS FAT (floppy like) file format, without a partition table */ + result = Check_for_DOS_FAT(0); + } + if ((csd_file_format & 0x0c00) == 0x0000) + { + /* SD Card contains files stored in a Hard disk-like file format that contains a partition table */ + if (Check_for_Master_Boot_Record()) + { + result = Check_for_DOS_FAT(fat_partition_offset_in_512_byte_sectors); + } + } + if (result == true) + { + // Accept only FAT16, not FAT12. + if (boot_sector_data.bits_for_cluster_index != 16) + { + result = false; + } + else + { + fat_partition_size_in_512_byte_sectors = boot_sector_data.number_of_sectors_in_partition; + } + } + } + } + return result; +} + + +static void filename_to_upper_case(char *file_name) +// Change file name to upper case. +{ + int index; + int length = strlen(file_name); + + for (index = 0; index < length; index++) + { + if ((file_name[index] >= 'a') && (file_name[index] <= 'z')) + { + file_name[index] = (file_name[index] - 'a') + 'A'; + } + } +} + + +static bool check_file_name_for_FAT16_compliance(char *file_name) +// Check if the file complies with FAT16 naming convention. +{ + int length = strlen(file_name); + int index; + int last_dir_break_position = -1; + int last_period = -1; + bool result = true; + + for(index = 0; index < length; index++) + { + if ((file_name[index] == ' ') || + ((last_dir_break_position == (index - 1)) && ((file_name[index] == '\\') || (file_name[index] == '/'))) || + ((index - last_period == 9) && (file_name[index] != '.')) || + ((last_dir_break_position != last_period) && (index - last_period > 3) && + (file_name[index] != '\\') && (file_name[index] != '/')) + ) + { + result = false; + break; + } + if ((file_name[index] == '\\') || (file_name[index] == '/')) + { + last_period = index; + last_dir_break_position = index; + } + if (file_name[index] == '.') + { + last_period = index; + } + } + if ((file_name[length-1] == '\\') || (file_name[length-1] == '/')) + { + result = false; + } + return result; +} + + +static int get_dir_divider_location(char *name) +// Find a directory divider location. +{ + int index = 0; + int length = strlen(name); + + for(index = 0; index < length; index++) + { + if ((name[index] == '\\') || (name[index] == '/')) + { + break; + } + } + + if (index == length) + { + index = -1; + } + + return index; +} + + +static bool match_file_record_to_name_ext(t_file_record *file_record, char *name, char *extension) +/* See if the given name and extension match the file record. Return true if this is so, false otherwise. */ +{ + bool match = true; + int index; + + for (index = 0; index < 8; index++) + { + if (CHAR_TO_UPPER(file_record->name[index]) != CHAR_TO_UPPER(name[index])) + { + match = false; + break; + } + } + for (index = 0; index < 3; index++) + { + if (CHAR_TO_UPPER(file_record->extension[index]) != CHAR_TO_UPPER(extension[index])) + { + match = false; + break; + } + } + return match; +} + + +static bool get_home_directory_cluster_for_file(char *file_name, int *home_directory_cluster, t_file_record *file_record) +// Scan the directories in given in the file name and find the root directory for the file. +{ + bool result = false; + int home_dir_cluster = 0; + int location, index; + int start_location = 0; + + /* Get Next Directory. */ + location = get_dir_divider_location( file_name ); + while (location > 0) + { + char name[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; + char extension[3] = { ' ', ' ', ' ' }; + int ext_index = -1; + int new_cluster = home_dir_cluster; + + // Get the name of the directory in name/extension format. + for (index = 0; index < location; index++) + { + if (file_name[index+start_location] == '.') + { + ext_index = index; + } + else if (ext_index < 0) + { + name[index] = file_name[index+start_location]; + } + else + { + extension[index-ext_index] = file_name[index+start_location]; + } + } + + if (home_dir_cluster == 0) + { + /* We are in the root directory. Scan the directory (of predefined size) and see if you can find the specified file. */ + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index; + + for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data(sector_index+boot_sector_data.root_directory_sector_offset, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, 0, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + if (match) + { + new_cluster = file_record->start_cluster_index; + file_record->file_record_cluster = 1; // Home directory is a subdirectory in the root directory. + break; + } + } + } + } + else + { + break; + } + if (new_cluster != home_dir_cluster) + { + break; + } + } + if (new_cluster != home_dir_cluster) + { + // A valid directory is found, so go to it. + home_dir_cluster = new_cluster; + start_location = start_location+location+1; + } + else + { + // Directory path is invalid. + return false; + } + } else { + // This is a subdirectory that can have any number of elements. So scan through it as though it was a file + // and see if you can find the directory of interest. + int cluster = home_dir_cluster; + + do { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index; + + for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, cluster, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + if (match) + { + new_cluster = file_record->start_cluster_index; + break; + } + } + } + } + else + { + break; + } + if (new_cluster != home_dir_cluster) + { + break; + } + } + // If this is the end of the cluster and the directory has not been found, then see if there is another cluster + // that holds data for the current directory. + if (new_cluster == home_dir_cluster) + { + unsigned short int next_cluster; + + if (get_cluster_flag(new_cluster, &next_cluster)) + { + // The directory needs to be expanded to store more files. + if ((next_cluster & 0x0000fff8) == 0x0000fff8) + { + return false; + } + new_cluster = (next_cluster & 0x0000fff8); + } + else + { + // Directory path is invalid. + return false; + } + } + } while ((cluster < 0x0000fff8) && (new_cluster == home_dir_cluster)); + if (new_cluster != home_dir_cluster) + { + // A valid directory is found, so go to it. + home_dir_cluster = new_cluster; + start_location = start_location+location+1; + } + else + { + // Directory path is invalid. + return false; + } + } + location = get_dir_divider_location(&(file_name[start_location])); + if (location < 0) + { + // Directory has been located. + result = true; + } + } + + *home_directory_cluster = home_dir_cluster; + if (home_dir_cluster == 0) + { + file_record->file_record_cluster = 0; // Home directory is the root directory. + result = true; + } + return result; +} + + +static bool find_file_in_directory(int directory_start_cluster, char *file_name, t_file_record *file_record) +// Given a cluster and a file name, check if the file already exists. Return the file record if the file is found. +{ + int location = get_dir_divider_location( file_name ); + int last_dir_separator = 0; + char name[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; + char extension[3] = { ' ', ' ', ' ' }; + int ext_index = -1; + int cluster = directory_start_cluster; + int index; + int length = strlen(file_name); + bool result = false; + + // Skip through all directory separators. + while (location > 0) + { + last_dir_separator = last_dir_separator+location+1; + location = get_dir_divider_location( &(file_name[last_dir_separator]) ); + } + + // Get the name of the file in name/extension format. + for (index = last_dir_separator; index < length; index++) + { + if (file_name[index] == '.') + { + ext_index = index; + } + else if (ext_index < 0) + { + name[index-last_dir_separator] = file_name[index]; + } + else + { + extension[index-ext_index-1] = file_name[index]; + } + } + + // Look for the file. + if (directory_start_cluster == 0) + { + /* We are in the root directory. Scan the directory (of predefined size) and see if you can find the specified file. */ + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index; + + for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, + fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, 0, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + + if (match) + { + result = true; + break; + } + } + } + } + else + { + break; + } + if (result) + { + break; + } + } + } + else + { + do { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index; + + for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + // Read file record. + Read_File_Record_At_Offset(file_counter*32, file_record, cluster, sector_index); + if ((file_record->name[0] != 0xe5) && (file_record->name[0] != 0x00)) + { + bool match = match_file_record_to_name_ext(file_record, name, extension); + + if (match) + { + result = true; + break; + } + } + } + } + else + { + break; + } + if (result) + { + break; + } + } + // If this is the end of the cluster and the file has not been found, then see if there is another cluster + // that holds data for the current directory. + if (result == false) + { + unsigned short int new_cluster; + + if (get_cluster_flag(cluster, &new_cluster)) + { + // The directory needs to be expanded to store more files. + if ((new_cluster & 0x0000fff8) == 0x0000fff8) + { + return false; + } + cluster = (new_cluster & 0x0000fff8); + } + else + { + // Directory path is invalid. + return false; + } + } + } while ((cluster < 0x0000fff8) && (result == false)); + } + + return result; +} + + +static bool find_first_empty_cluster(unsigned int *cluster_number) +// Find the first empty cluster. It will be marked by a 0 entry in the File Allocation Table. +{ + unsigned int sector = boot_sector_data.first_fat_sector_offset; + unsigned int cluster_index = 2; + short int cluster = -1; + bool result = false; + unsigned max_cluster_index = 0; + unsigned int non_data_sectors = boot_sector_data.data_sector_offset; + unsigned int less_than_32 = boot_sector_data.number_of_sectors_in_partition; + unsigned int greater_than_32 = boot_sector_data.total_sector_count_if_above_32MB; + + if (less_than_32 > greater_than_32) + { + max_cluster_index = ((less_than_32 - non_data_sectors) / boot_sector_data.sectors_per_cluster) + 1; + } + else + { + max_cluster_index = ((greater_than_32 - non_data_sectors) / boot_sector_data.sectors_per_cluster) + 1; + } + // Find an empty cluster for the file. + while (sector != boot_sector_data.second_fat_sector_offset) + { + if (Read_Sector_Data( sector, fat_partition_offset_in_512_byte_sectors)) + { + do { + cluster = ((unsigned short int) IORD_16DIRECT(device_pointer->base, 2*(cluster_index % 256))); + if (cluster == 0) + { + // Free cluster found. + break; + } + else + { + cluster_index++; + } + } while ((cluster_index % 256) != 0); + } + if (cluster == 0) + { + break; + } + sector++; + } + if ((cluster == 0) && (cluster <= max_cluster_index)) + { + *cluster_number = cluster_index; + result = true; + } + return result; +} + + +static int find_first_empty_record_in_a_subdirectory(int start_cluster_index) +// Search for a free spot in a subdirectory. Return an encoded location for the file record. +{ + int result = -1; + int cluster = start_cluster_index; + do { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index; + + for (sector_index = 0; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + unsigned short int leading_char; + + // Read file record. + leading_char = ((unsigned char) IORD_8DIRECT(device_pointer->base, file_counter*32)); + if ((leading_char == 0x00e5) || (leading_char == 0)) + { + result = (cluster) | ((sector_index*16 + file_counter) << 16); + return result; + } + } + } + else + { + break; + } + } + // If this is the end of the cluster and the file has not been found, then see if there is another cluster + // that holds data for the current directory. + if (result < 0) + { + unsigned short int new_cluster; + if (get_cluster_flag(cluster, &new_cluster)) + { + // The directory needs to be expanded to store more files. + if ((new_cluster & 0x0000fff8) == 0x0000fff8) + { + unsigned int new_dir_cluster; + if (find_first_empty_cluster(&new_dir_cluster)) + { + // Add the new cluster to the linked list of the given directory. + if (mark_cluster(cluster, ((short int) (new_dir_cluster)), true) && + mark_cluster(new_dir_cluster, ((short int) (0xffff)), true) && + mark_cluster(cluster, ((short int) (new_dir_cluster)), false) && + mark_cluster(new_dir_cluster, ((short int) (0xffff)), false)) + { + Save_Modified_Sector(); + // The new file will begin at the first entry of the directory. + result = new_dir_cluster; + } + } + cluster = (new_cluster & 0x0000fff8); + } + } + else + { + // Error encountered. + result = -1; + } + } + } while ((cluster < 0x0000fff8) && (result == -1)); + return result; +} + + +static int find_first_empty_record_in_root_directory() +// Find a first unused record location to use. Return -1 if none is found. +{ + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index; + int result = -1; + + for (sector_index = 0; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, + fat_partition_offset_in_512_byte_sectors)) + { + int file_counter; + + for (file_counter = 0; file_counter < 16; file_counter++) + { + unsigned short int leading_char; + + // Read first character of the file record. + leading_char = ((unsigned char) IORD_8DIRECT(device_pointer->base, file_counter*32)); + if ((leading_char == 0x00e5) || (leading_char == 0)) + { + result = (sector_index*16 + file_counter) << 16; + return result; + } + } + } + else + { + break; + } + } + return result; +} + +static void convert_filename_to_name_extension(char *filename, char *name, char *extension) +// This function converts the file name into a name . extension format. +{ + int counter; + int local = 0; + + for(counter = 0; counter < 8; counter++) + { + if (filename[local] != '.') + { + name[counter] = filename[local]; + if (filename[local] != 0) local++; + } + else + { + name[counter] = ' '; + } + } + if (filename[local] == '.') local++; + for(counter = 0; counter < 3; counter++) + { + if (filename[local] != 0) + { + extension[counter] = filename[local]; + local++; + } + else + { + extension[counter] = ' '; + } + } + +} + +static bool create_file(char *name, t_file_record *file_record, t_file_record *home_dir) +// Create a file in a given directory. Expand the directory if needed. +{ + unsigned int cluster_number; + bool result = false; + + if (find_first_empty_cluster(&cluster_number)) + { + int record_index; + + if (home_dir->file_record_cluster == 0) + { + // Put a file in the root directory. + record_index = find_first_empty_record_in_root_directory(); + } + else + { + // Put a file in a subdirectory. + record_index = find_first_empty_record_in_a_subdirectory(home_dir->start_cluster_index); + } + if (record_index >= 0) + { + unsigned int file_record_sector; + int location = get_dir_divider_location( name ); + int last_dir_separator = 0; + + // Skip through all directory separators. + while (location > 0) + { + last_dir_separator = last_dir_separator+location+1; + location = get_dir_divider_location( &(name[last_dir_separator]) ); + } + + convert_filename_to_name_extension(&(name[last_dir_separator]), (char *)file_record->name, (char *)file_record->extension); + + file_record->attributes = 0; + file_record->create_time = 0; + file_record->create_date = 0; + file_record->last_access_date = 0; + file_record->last_modified_time = 0; + file_record->last_modified_date = 0; + file_record->start_cluster_index = cluster_number; + file_record->file_size_in_bytes = 0; + file_record->current_cluster_index = cluster_number; + file_record->current_sector_in_cluster = 0; + file_record->current_byte_position = 0; + file_record->file_record_cluster = record_index & 0x0000ffff; + file_record->file_record_sector_in_cluster = ((record_index >> 16) & 0x0000ffff) / 16; + file_record->file_record_offset = (((record_index >> 16) & 0x0000ffff) % 16)*32; + file_record->home_directory_cluster = home_dir->start_cluster_index; + file_record->in_use = true; + file_record->modified = true; + // Now write the record at the specified location. + file_record_sector = (file_record->file_record_cluster == 0) ? + (boot_sector_data.root_directory_sector_offset + file_record->file_record_sector_in_cluster): + (boot_sector_data.data_sector_offset + (file_record->file_record_cluster-2)*boot_sector_data.sectors_per_cluster + + file_record->file_record_sector_in_cluster); + + if (Read_Sector_Data(file_record_sector, fat_partition_offset_in_512_byte_sectors)) + { + if (Write_File_Record_At_Offset(file_record->file_record_offset, file_record)) + { + Save_Modified_Sector(); + // Mark the first cluster of the file as the last cluster at first. + mark_cluster(cluster_number, ((short int) (0xffff)), true); + if (mark_cluster(cluster_number, ((short int) (0xffff)), false)) + { + result = true; + } + } + } + } + + } + return result; +} + + +static void copy_file_record_name_to_string(t_file_record *file_record, char *file_name) +/* Copy a file name from the file record to a given string */ +{ + int index; + int flength = 0; + + /* Copy file name.*/ + for (index = 0; index < 8; index++) + { + if (file_record->name[index] != ' ') + { + file_name[flength] = file_record->name[index]; + flength = flength + 1; + } + } + if (file_record->extension[0] != ' ') + { + file_name[flength] = '.'; + flength = flength + 1; + for (index = 0; index < 3; index++) + { + if (file_record->extension[index] != ' ') + { + file_name[flength] = file_record->extension[index]; + flength = flength + 1; + } + } + } + file_name[flength] = 0; +} +#endif //SD_RAW_IFACE + +/////////////////////////////////////////////////////////////////////////// +// Direct functions +/////////////////////////////////////////////////////////////////////////// + + +alt_up_sd_card_dev* alt_up_sd_card_open_dev(const char* name) +{ + // find the device from the device list + // (see altera_hal/HAL/inc/priv/alt_file.h + // and altera_hal/HAL/src/alt_find_dev.c + // for details) + alt_up_sd_card_dev *dev = (alt_up_sd_card_dev *) alt_find_dev(name, &alt_dev_list); + + if (dev != NULL) + { + aux_status_register = ((short int *) SD_CARD_AUX_STATUS(dev->base)); + status_register = ((int *) SD_CARD_STATUS(dev->base)); + CSD_register_w0 = ((short int *) SD_CARD_CSD(dev->base, 0)); + command_register = ((short int *) SD_CARD_COMMAND(dev->base)); + command_argument_register = ((int *) SD_CARD_ARGUMENT(dev->base)); + buffer_memory = (char *) SD_CARD_BUFFER(dev->base, 0); + device_pointer = dev; + initialized = false; +#ifndef SD_RAW_IFACE + is_sd_card_formated_as_FAT16 = false; + search_data.valid = false; +#endif + } + return dev; +} + + +bool alt_up_sd_card_is_Present(void) +// Check if there is an SD Card insterted into the SD Card socket. +{ + bool result = false; + + if ((device_pointer != NULL) && ((IORD_16DIRECT(aux_status_register,0) & 0x02) != 0)) + { + result = true; + } + else if (initialized == true) + { + int index; + + initialized = false; +#ifndef SD_RAW_IFACE + search_data.valid = false; + is_sd_card_formated_as_FAT16 = false; + + for(index = 0; index < MAX_FILES_OPENED; index++) + { + active_files[index].in_use = false; + active_files[index].modified = false; + } +#endif + } + return result; +} + +#ifndef SD_RAW_IFACE +bool alt_up_sd_card_is_FAT16(void) +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + * If the card contains a FAT16 volume, the local data structures will be initialized to allow reading and writing + * to the SD card as though it was a hard drive. + */ +{ + bool result = false; + + if (alt_up_sd_card_is_Present()) + { + // Check if an SD Card is in the SD Card slot. + if (initialized == false) + { + // Now determine if the card is formatted as FAT 16. + is_sd_card_formated_as_FAT16 = Look_for_FAT16(); + initialized = is_sd_card_formated_as_FAT16; + search_data.valid = false; + } + result = is_sd_card_formated_as_FAT16; + } + else + { + // If not then you may as well not open the device. + initialized = false; + is_sd_card_formated_as_FAT16 = false; + } + + return result; +} + + +short int alt_up_sd_card_find_first(char *directory_to_search_through, char *file_name) +/* This function sets up a search algorithm to go through a given directory looking for files. + * If the search directory is valid, then the function searches for the first file it finds. + * Inputs: + * directory_to_search_through - name of the directory to search through + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * 0 - success + * 1 - invalid directory + * 2 - No card or incorrect card format. + * + * To specify a directory give the name in a format consistent with the following regular expression: + * [{[valid_chars]+}/]*. + * + * In other words, give a path name starting at the root directory, where each directory name is followed by a '/'. + * Then, append a '.' to the directory name. Examples: + * "." - look through the root directory + * "first/." - look through a directory named "first" that is located in the root directory. + * "first/sub/." - look through a directory named "sub", that is located within the subdirectory named "first". "first" is located in the root directory. + * Invalid examples include: + * "/.", "/////." - this is not the root directory. + * "/first/." - the first character may not be a '/'. + */ +{ + short int result = 2; + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + int home_directory_cluster; + t_file_record file_record; + + if (get_home_directory_cluster_for_file(directory_to_search_through, &home_directory_cluster, &file_record)) + { + search_data.directory_root_cluster = home_directory_cluster; + search_data.current_cluster_index = home_directory_cluster; + search_data.current_sector_in_cluster = 0; + search_data.file_index_in_sector = -1; + search_data.valid = true; + result = alt_up_sd_card_find_next(file_name); + } + else + { + result = 1; + } + } + return result; +} + + +short int alt_up_sd_card_find_next(char *file_name) +/* This function searches for the next file in a given directory, as specified by the find_first function. + * Inputs: + * file_name - an array to store a name of the file found. Must be 13 bytes long (12 bytes for file name and 1 byte of NULL termination). + * Outputs: + * -1 - end of directory. + * 0 - success + * 2 - No card or incorrect card format. + * 3 - find_first has not been called successfully. + */ +{ + short int result = 2; + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + if (search_data.valid) + { + t_file_record file_record; + int cluster = search_data.current_cluster_index; + + if (cluster == 0) + { + // Searching through the root directory + int max_root_dir_sectors = ((32*boot_sector_data.max_number_of_dir_entires) / boot_sector_data.sector_size_in_bytes); + int sector_index = search_data.current_sector_in_cluster; + int file_counter = search_data.file_index_in_sector+1; + + for (; sector_index < max_root_dir_sectors; sector_index++) + { + if (Read_Sector_Data( sector_index + boot_sector_data.root_directory_sector_offset, + fat_partition_offset_in_512_byte_sectors)) + { + for (; file_counter < 16; file_counter++) + { + if (Read_File_Record_At_Offset(file_counter*32, &file_record, 0, sector_index)) + { + if ((file_record.name[0] != 0) && (file_record.name[0] != 0xe5)) + { + /* Update search structure. */ + search_data.file_index_in_sector = file_counter; + search_data.current_sector_in_cluster = sector_index; + + /* Copy file name.*/ + copy_file_record_name_to_string(&file_record, file_name); + return 0; + } + } + } + file_counter = 0; + } + else + { + break; + } + } + result = -1; + } + else + { + int file_counter = search_data.file_index_in_sector+1; + do + { + int start_sector = ( cluster - 2 ) * ( boot_sector_data.sectors_per_cluster ) + boot_sector_data.data_sector_offset; + int sector_index = search_data.current_sector_in_cluster; + + for (; sector_index < boot_sector_data.sectors_per_cluster; sector_index++) + { + if (Read_Sector_Data(sector_index + start_sector, fat_partition_offset_in_512_byte_sectors)) + { + for (; file_counter < 16; file_counter++) + { + if (Read_File_Record_At_Offset(file_counter*32, &file_record, cluster, sector_index)) + { + if ((file_record.name[0] != 0) && (file_record.name[0] != 0xe5)) + { + /* Update search structure. */ + search_data.current_cluster_index = cluster; + search_data.file_index_in_sector = file_counter; + search_data.current_sector_in_cluster = sector_index; + + /* Copy file name.*/ + copy_file_record_name_to_string(&file_record, file_name); + return 0; + } + } + } + file_counter = 0; + } + else + { + break; + } + } + // If this is the end of the cluster and the file has not been found, then see if there is another cluster + // that holds data for the current directory. + if (sector_index >= boot_sector_data.sectors_per_cluster) + { + unsigned short int new_cluster; + + if (get_cluster_flag(cluster, &new_cluster)) + { + if ((new_cluster & 0x0000fff8) == 0x0000fff8) + { + result = -1; + search_data.valid = false; + } + cluster = ((new_cluster) & 0x0000fff8); + } + else + { + // Error encountered. + result = -1; + } + } + } while (cluster < 0x0000fff8); + } + } + else + { + // Call Find_First first. + result = 3; + } + } + return result; +} + + +short int alt_up_sd_card_fopen(char *name, bool create) +/* This function reads the SD card data in an effort to determine if the card is formated as a FAT16 + * volume. Please note that FAT12 has a similar format, but will not be supported by this driver. + * + * Inputs: + * name - a file name including a directory, relative to the root directory + * create - a flag set to true to create a file if it does not already exist + * Output: + * An index to the file record assigned to the specified file. -1 is returned if the file could not be opened. + * Return -2 if the specified file has already been opened previously. + */ +{ + short int file_record_index = -1; + + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + unsigned int home_directory_cluster = 0; + t_file_record home_dir; + + /* First check the file name format. It should not be longer than 12 characters, including a period and the extension. + * Rules: + * - no spaces + * - at most 12 chatacters per name, with a period in 9th position. + * - a / or a \ every at most 12 characters. + */ + filename_to_upper_case(name); + if (check_file_name_for_FAT16_compliance(name)) + { + int index; + + /* Get home directory cluster location for the specified file. 0 means root directory. */ + if (!get_home_directory_cluster_for_file(name, (int *) &home_directory_cluster, &home_dir)) + { + return file_record_index; + } + + /* Find a free file slot to store file specs in. */ + for (index = 0; index < MAX_FILES_OPENED; index++) + { + if (active_files[index].in_use == false) + { + file_record_index = index; + break; + } + } + if (file_record_index >= 0) + { + /* If file record is found, then look for the specified file. If the create flag is set to true + * and the file is not found, then it should be created in the current directory. + */ + + if (find_file_in_directory(home_directory_cluster, name, &(active_files[file_record_index]))) + { + if (create) + { + /* Do not allow overwriting existing files for now. */ + return -1; + } + active_files[file_record_index].current_cluster_index = active_files[file_record_index].start_cluster_index; + active_files[file_record_index].current_sector_in_cluster = 0; + active_files[file_record_index].current_byte_position = 0; + active_files[file_record_index].in_use = true; + active_files[file_record_index].modified = false; + + /* Check if the file has already been opened. */ + for (index = 0; index < MAX_FILES_OPENED; index++) + { + if ((file_record_index != index) && (active_files[index].in_use == true)) + { + if ((active_files[file_record_index].file_record_cluster == active_files[index].file_record_cluster) && + (active_files[file_record_index].file_record_sector_in_cluster == active_files[index].file_record_sector_in_cluster) && + (active_files[file_record_index].file_record_offset == active_files[index].file_record_offset)) + { + // file already in use. + file_record_index = -2; + break; + } + } + } + + } + else if (create) + { + /* Create file if needed. */ + if (create_file(name, &(active_files[file_record_index]), &home_dir)) + { + active_files[file_record_index].in_use = true; + active_files[file_record_index].modified = true; + } + else + { + /* If file creation fails then return an invalid file handle. */ + file_record_index = -1; + } + } + else + { + /* Otherwise the file could not be opened.*/ + file_record_index = -1; + } + } + } + } + + return file_record_index; +} + + +void alt_up_sd_card_set_attributes(short int file_handle, short int attributes) +/* Return file attributes, or -1 if the file_handle is invalid. + */ +{ + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + active_files[file_handle].attributes = ((char)(attributes & 0x00ff)); + } + } +} + + +short int alt_up_sd_card_get_attributes(short int file_handle) +/* Return file attributes, or -1 if the file_handle is invalid. + */ +{ + short int result = -1; + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + result = ((active_files[file_handle].attributes) & 0x00ff); + } + } + return result; +} + +short int alt_up_sd_card_read(short int file_handle) +/* Read a single character from a given file. Return -1 if at the end of a file. Any other negative number + * means that the file could not be read. A number between 0 and 255 is an ASCII character read from the SD Card. */ +{ + short int ch = -1; + + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + if (active_files[file_handle].current_byte_position < active_files[file_handle].file_size_in_bytes) + { + int data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + + if ((active_files[file_handle].current_byte_position > 0) && ((active_files[file_handle].current_byte_position % 512) == 0)) + { + // Read in a new sector of data. + if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) + { + // Go to the next cluster. + unsigned short int next_cluster; + if (get_cluster_flag(active_files[file_handle].current_cluster_index, &next_cluster)) + { + if ((next_cluster & 0x0000fff8) == 0x0000fff8) + { + /* End of file */ + return -1; + } + else + { + active_files[file_handle].current_cluster_index = next_cluster; + active_files[file_handle].current_sector_in_cluster = 0; + data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + } + } + else + { + return -2; + } + } + else + { + active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_sector_in_cluster + 1; + data_sector = data_sector + 1; + } + } + // Reading te first byte of the file. + if (current_sector_index != (data_sector + fat_partition_offset_in_512_byte_sectors)) + { + if (!Read_Sector_Data(data_sector, fat_partition_offset_in_512_byte_sectors)) + { + return -2; + } + } + + ch = (unsigned char) IORD_8DIRECT(buffer_memory, (active_files[file_handle].current_byte_position % 512)); + active_files[file_handle].current_byte_position = active_files[file_handle].current_byte_position + 1; + } + } + } + + return ch; +} + + +bool alt_up_sd_card_write(short int file_handle, char byte_of_data) +/* Write a single character to a given file. Return true if successful, and false otherwise. */ +{ + bool result = false; + + if ((file_handle >= 0) && (file_handle < MAX_FILES_OPENED)) + { + if (active_files[file_handle].in_use) + { + int data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + short int buffer_offset = active_files[file_handle].current_byte_position % boot_sector_data.sector_size_in_bytes; + + if (active_files[file_handle].current_byte_position < active_files[file_handle].file_size_in_bytes) + { + if ((active_files[file_handle].current_byte_position > 0) && (buffer_offset == 0)) + { + // Read in a new sector of data. + if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) + { + // Go to the next cluster. + unsigned short int next_cluster; + if (get_cluster_flag(active_files[file_handle].current_cluster_index, &next_cluster)) + { + if (next_cluster < 0x0000fff8) + { + active_files[file_handle].current_cluster_index = next_cluster; + active_files[file_handle].current_sector_in_cluster = 0; + data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + } + } + else + { + return false; + } + } + else + { + active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_sector_in_cluster + 1; + data_sector = data_sector + 1; + } + } + } + else + { + /* You are adding data to the end of the file, so increment its size and look for an additional data cluster if needed. */ + if ((active_files[file_handle].current_byte_position > 0) && (buffer_offset == 0)) + { + if (active_files[file_handle].current_sector_in_cluster == boot_sector_data.sectors_per_cluster - 1) + { + /* Find a new cluster if possible. */ + unsigned int cluster_number; + + if (find_first_empty_cluster(&cluster_number)) + { + // mark clusters in both File Allocation Tables. + mark_cluster(active_files[file_handle].current_cluster_index, ((unsigned short int) (cluster_number & 0x0000ffff)), true); + mark_cluster(cluster_number, 0xffff, true); + mark_cluster(active_files[file_handle].current_cluster_index, ((unsigned short int) (cluster_number & 0x0000ffff)), false); + mark_cluster(cluster_number, 0xffff, false); + // Change cluster index and sector index to compute a new data sector. + active_files[file_handle].current_cluster_index = cluster_number; + active_files[file_handle].current_sector_in_cluster = 0; + } + else + { + return false; + } + } + else + { + /* Read the next sector in the cluster and modify it. We only need to change the data_sector value. The actual read happens a few lines below. */ + active_files[file_handle].current_sector_in_cluster = active_files[file_handle].current_byte_position / boot_sector_data.sector_size_in_bytes; + } + data_sector = boot_sector_data.data_sector_offset + (active_files[file_handle].current_cluster_index - 2)*boot_sector_data.sectors_per_cluster + + active_files[file_handle].current_sector_in_cluster; + } + } + // Reading a data sector into the buffer. Note that changes to the most recently modified sector will be saved before + // a new sector is read from the SD Card. + if (current_sector_index != data_sector + fat_partition_offset_in_512_byte_sectors) + { + if (!Read_Sector_Data(data_sector, fat_partition_offset_in_512_byte_sectors)) + { + return false; + } + } + // Write a byte of data to the buffer. + IOWR_8DIRECT(buffer_memory, buffer_offset, byte_of_data); + active_files[file_handle].current_byte_position = active_files[file_handle].current_byte_position + 1; + + // Modify the file record only when necessary. + if (active_files[file_handle].current_byte_position >= active_files[file_handle].file_size_in_bytes) + { + active_files[file_handle].file_size_in_bytes = active_files[file_handle].file_size_in_bytes + 1; + active_files[file_handle].modified = true; + } + // Invaldiate the buffer to ensure that the buffer contents are written to the SD card whe nthe file is closed. + current_sector_modified = true; + result = true; + } + } + + return result; +} + + +bool alt_up_sd_card_fclose(short int file_handle) +// This function closes an opened file and saves data to SD Card if necessary. +{ + bool result = false; + if ((alt_up_sd_card_is_Present()) && (is_sd_card_formated_as_FAT16)) + { + if (active_files[file_handle].in_use) + { + if (active_files[file_handle].modified) + { + unsigned int record_sector = active_files[file_handle].file_record_sector_in_cluster; + if (active_files[file_handle].file_record_cluster == 0) + { + record_sector = record_sector + boot_sector_data.root_directory_sector_offset; + } + else + { + record_sector = record_sector + boot_sector_data.data_sector_offset + + (active_files[file_handle].file_record_cluster - 2)*boot_sector_data.sectors_per_cluster; + } + if (Read_Sector_Data(record_sector, fat_partition_offset_in_512_byte_sectors)) + { + if (Write_File_Record_At_Offset(active_files[file_handle].file_record_offset, &(active_files[file_handle]))) + { + // Make sure that the Data has been saved to the SD Card. + result = Save_Modified_Sector(); + } + } + } + active_files[file_handle].in_use = false; + result = true; + } + } + + return result; +} + +#endif //SD_RAW_IFACE diff --git a/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_fd.c b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_fd.c new file mode 100644 index 0000000..53dfc3b --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_fd.c @@ -0,0 +1,86 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include "alt_types.h" +#include "sys/alt_dev.h" +#include "altera_avalon_jtag_uart.h" + +extern int altera_avalon_jtag_uart_read(altera_avalon_jtag_uart_state* sp, + char* buffer, int space, int flags); +extern int altera_avalon_jtag_uart_write(altera_avalon_jtag_uart_state* sp, + const char* ptr, int count, int flags); +extern int altera_avalon_jtag_uart_ioctl(altera_avalon_jtag_uart_state* sp, + int req, void* arg); +extern int altera_avalon_jtag_uart_close(altera_avalon_jtag_uart_state* sp, + int flags); + +/* ----------------------------------------------------------------------- */ +/* --------------------- WRAPPERS FOR ALT FD SUPPORT --------------------- */ +/* + * + */ + +int +altera_avalon_jtag_uart_read_fd(alt_fd* fd, char* buffer, int space) +{ + altera_avalon_jtag_uart_dev* dev = (altera_avalon_jtag_uart_dev*) fd->dev; + + return altera_avalon_jtag_uart_read(&dev->state, buffer, space, + fd->fd_flags); +} + +int +altera_avalon_jtag_uart_write_fd(alt_fd* fd, const char* buffer, int space) +{ + altera_avalon_jtag_uart_dev* dev = (altera_avalon_jtag_uart_dev*) fd->dev; + + return altera_avalon_jtag_uart_write(&dev->state, buffer, space, + fd->fd_flags); +} + +#ifndef ALTERA_AVALON_JTAG_UART_SMALL + +int +altera_avalon_jtag_uart_close_fd(alt_fd* fd) +{ + altera_avalon_jtag_uart_dev* dev = (altera_avalon_jtag_uart_dev*) fd->dev; + + return altera_avalon_jtag_uart_close(&dev->state, fd->fd_flags); +} + +int +altera_avalon_jtag_uart_ioctl_fd(alt_fd* fd, int req, void* arg) +{ + altera_avalon_jtag_uart_dev* dev = (altera_avalon_jtag_uart_dev*) fd->dev; + + return altera_avalon_jtag_uart_ioctl(&dev->state, req, arg); +} + +#endif /* ALTERA_AVALON_JTAG_UART_SMALL */ diff --git a/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_init.c b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_init.c new file mode 100644 index 0000000..7317bec --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_init.c @@ -0,0 +1,256 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2007 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "sys/alt_irq.h" +#include "sys/alt_alarm.h" +#include "sys/ioctl.h" +#include "alt_types.h" + +#include "altera_avalon_jtag_uart_regs.h" +#include "altera_avalon_jtag_uart.h" + +#include "sys/alt_log_printf.h" + +#ifndef ALTERA_AVALON_JTAG_UART_SMALL + +/* ----------------------------------------------------------- */ +/* ------------------------- FAST DRIVER --------------------- */ +/* ----------------------------------------------------------- */ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT +static void altera_avalon_jtag_uart_irq(void* context); +#else +static void altera_avalon_jtag_uart_irq(void* context, alt_u32 id); +#endif +static alt_u32 altera_avalon_jtag_uart_timeout(void* context); + +/* + * Driver initialization code. Register interrupts and start a timer + * which we can use to check whether the host is there. + * Return 1 on sucessful IRQ register and 0 on failure. + */ + +void altera_avalon_jtag_uart_init(altera_avalon_jtag_uart_state* sp, + int irq_controller_id, int irq) +{ + ALT_FLAG_CREATE(&sp->events, 0); + ALT_SEM_CREATE(&sp->read_lock, 1); + ALT_SEM_CREATE(&sp->write_lock, 1); + + /* enable read interrupts at the device */ + sp->irq_enable = ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK; + + IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable); + + /* register the interrupt handler */ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT + alt_ic_isr_register(irq_controller_id, irq, altera_avalon_jtag_uart_irq, + sp, NULL); +#else + alt_irq_register(irq, sp, altera_avalon_jtag_uart_irq); +#endif + + /* Register an alarm to go off every second to check for presence of host */ + sp->host_inactive = 0; + + if (alt_alarm_start(&sp->alarm, alt_ticks_per_second(), + &altera_avalon_jtag_uart_timeout, sp) < 0) + { + /* If we can't set the alarm then record "don't know if host present" + * and behave as though the host is present. + */ + sp->timeout = INT_MAX; + } + + /* ALT_LOG - see altera_hal/HAL/inc/sys/alt_log_printf.h */ + ALT_LOG_JTAG_UART_ALARM_REGISTER(sp, sp->base); +} + +/* + * Interrupt routine + */ +#ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT +static void altera_avalon_jtag_uart_irq(void* context) +#else +static void altera_avalon_jtag_uart_irq(void* context, alt_u32 id) +#endif +{ + altera_avalon_jtag_uart_state* sp = (altera_avalon_jtag_uart_state*) context; + unsigned int base = sp->base; + + /* ALT_LOG - see altera_hal/HAL/inc/sys/alt_log_printf.h */ + ALT_LOG_JTAG_UART_ISR_FUNCTION(base, sp); + + for ( ; ; ) + { + unsigned int control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base); + + /* Return once nothing more to do */ + if ((control & (ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK | ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK)) == 0) + break; + + if (control & ALTERA_AVALON_JTAG_UART_CONTROL_RI_MSK) + { + /* process a read irq. Start by assuming that there is data in the + * receive FIFO (otherwise why would we have been interrupted?) + */ + unsigned int data = 1 << ALTERA_AVALON_JTAG_UART_DATA_RAVAIL_OFST; + + for ( ; ; ) + { + /* Check whether there is space in the buffer. If not then we must not + * read any characters from the buffer as they will be lost. + */ + unsigned int next = (sp->rx_in + 1) % ALTERA_AVALON_JTAG_UART_BUF_LEN; + if (next == sp->rx_out) + break; + + /* Try to remove a character from the FIFO and find out whether there + * are any more characters remaining. + */ + data = IORD_ALTERA_AVALON_JTAG_UART_DATA(base); + + if ((data & ALTERA_AVALON_JTAG_UART_DATA_RVALID_MSK) == 0) + break; + + sp->rx_buf[sp->rx_in] = (data & ALTERA_AVALON_JTAG_UART_DATA_DATA_MSK) >> ALTERA_AVALON_JTAG_UART_DATA_DATA_OFST; + sp->rx_in = (sp->rx_in + 1) % ALTERA_AVALON_JTAG_UART_BUF_LEN; + + /* Post an event to notify jtag_uart_read that a character has been read */ + ALT_FLAG_POST (sp->events, ALT_JTAG_UART_READ_RDY, OS_FLAG_SET); + } + + if (data & ALTERA_AVALON_JTAG_UART_DATA_RAVAIL_MSK) + { + /* If there is still data available here then the buffer is full + * so turn off receive interrupts until some space becomes available. + */ + sp->irq_enable &= ~ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK; + IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(base, sp->irq_enable); + + /* Dummy read to ensure IRQ is cleared prior to ISR completion */ + IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base); + } + } + + if (control & ALTERA_AVALON_JTAG_UART_CONTROL_WI_MSK) + { + /* process a write irq */ + unsigned int space = (control & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK) >> ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_OFST; + + while (space > 0 && sp->tx_out != sp->tx_in) + { + IOWR_ALTERA_AVALON_JTAG_UART_DATA(base, sp->tx_buf[sp->tx_out]); + + sp->tx_out = (sp->tx_out + 1) % ALTERA_AVALON_JTAG_UART_BUF_LEN; + + /* Post an event to notify jtag_uart_write that a character has been written */ + ALT_FLAG_POST (sp->events, ALT_JTAG_UART_WRITE_RDY, OS_FLAG_SET); + + space--; + } + + if (space > 0) + { + /* If we don't have any more data available then turn off the TX interrupt */ + sp->irq_enable &= ~ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK; + IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable); + + /* Dummy read to ensure IRQ is cleared prior to ISR completion */ + IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base); + } + } + } +} + +/* + * Timeout routine is called every second + */ + +static alt_u32 +altera_avalon_jtag_uart_timeout(void* context) +{ + altera_avalon_jtag_uart_state* sp = (altera_avalon_jtag_uart_state *) context; + + unsigned int control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base); + + if (control & ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK) + { + IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable | ALTERA_AVALON_JTAG_UART_CONTROL_AC_MSK); + sp->host_inactive = 0; + } + else if (sp->host_inactive < INT_MAX - 2) { + sp->host_inactive++; + + if (sp->host_inactive >= sp->timeout) { + /* Post an event to indicate host is inactive (for jtag_uart_read */ + ALT_FLAG_POST (sp->events, ALT_JTAG_UART_TIMEOUT, OS_FLAG_SET); + } + } + + return alt_ticks_per_second(); +} + +/* + * The close() routine is implemented to drain the JTAG UART transmit buffer + * when not in "small" mode. This routine will wait for transimt data to be + * emptied unless a timeout from host-activity occurs. If the driver flags + * have been set to non-blocking mode, this routine will exit immediately if + * any data remains. This routine should be called indirectly (i.e. though + * the C library close() routine) so that the file descriptor associated + * with the relevant stream (i.e. stdout) can be closed as well. This routine + * does not manage file descriptors. + * + * The close routine is not implemented for the small driver; instead it will + * map to null. This is because the small driver simply waits while characters + * are transmitted; there is no interrupt-serviced buffer to empty + */ +int altera_avalon_jtag_uart_close(altera_avalon_jtag_uart_state* sp, int flags) +{ + /* + * Wait for all transmit data to be emptied by the JTAG UART ISR, or + * for a host-inactivity timeout, in which case transmit data will be lost + */ + while ( (sp->tx_out != sp->tx_in) && (sp->host_inactive < sp->timeout) ) { + if (flags & O_NONBLOCK) { + return -EWOULDBLOCK; + } + } + + return 0; +} + +#endif /* !ALTERA_AVALON_JTAG_UART_SMALL */ diff --git a/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_ioctl.c b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_ioctl.c new file mode 100644 index 0000000..cf71e6f --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_ioctl.c @@ -0,0 +1,86 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "sys/ioctl.h" +#include "alt_types.h" + +#include "altera_avalon_jtag_uart_regs.h" +#include "altera_avalon_jtag_uart.h" + +#include "sys/alt_log_printf.h" + +#ifndef ALTERA_AVALON_JTAG_UART_SMALL + +/* ----------------------------------------------------------- */ +/* ------------------------- FAST DRIVER --------------------- */ +/* ----------------------------------------------------------- */ + +int +altera_avalon_jtag_uart_ioctl(altera_avalon_jtag_uart_state* sp, int req, + void* arg) +{ + int rc = -ENOTTY; + + switch (req) + { + case TIOCSTIMEOUT: + /* Set the time to wait until assuming host is not connected */ + if (sp->timeout != INT_MAX) + { + int timeout = *((int *)arg); + sp->timeout = (timeout >= 2 && timeout < INT_MAX) ? timeout : INT_MAX - 1; + rc = 0; + } + break; + + case TIOCGCONNECTED: + /* Find out whether host is connected */ + if (sp->timeout != INT_MAX) + { + *((int *)arg) = (sp->host_inactive < sp->timeout) ? 1 : 0; + rc = 0; + } + break; + + default: + break; + } + + return rc; +} + +#endif /* !ALTERA_AVALON_JTAG_UART_SMALL */ diff --git a/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_read.c b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_read.c new file mode 100644 index 0000000..5657adb --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_read.c @@ -0,0 +1,205 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "sys/alt_irq.h" +#include "sys/alt_alarm.h" +#include "sys/ioctl.h" +#include "alt_types.h" + +#include "altera_avalon_jtag_uart_regs.h" +#include "altera_avalon_jtag_uart.h" + +#include "sys/alt_log_printf.h" + +#ifdef __ucosii__ +#include "includes.h" +#endif /* __ucosii__ */ + +#ifdef ALTERA_AVALON_JTAG_UART_SMALL + +/* ----------------------------------------------------------- */ +/* ----------------------- SMALL DRIVER ---------------------- */ +/* ----------------------------------------------------------- */ + +/* Read routine. The small version blocks until it has at least one byte + * available, it then returns as much as is immediately available without + * waiting any more. It's performance will be very poor without + * interrupts. + */ + +int +altera_avalon_jtag_uart_read(altera_avalon_jtag_uart_state* sp, + char* buffer, int space, int flags) +{ + unsigned int base = sp->base; + + char * ptr = buffer; + char * end = buffer + space; + + while (ptr < end) + { + unsigned int data = IORD_ALTERA_AVALON_JTAG_UART_DATA(base); + + if (data & ALTERA_AVALON_JTAG_UART_DATA_RVALID_MSK) + *ptr++ = (data & ALTERA_AVALON_JTAG_UART_DATA_DATA_MSK) >> ALTERA_AVALON_JTAG_UART_DATA_DATA_OFST; + else if (ptr != buffer) + break; + else if(flags & O_NONBLOCK) + break; + + } + + if (ptr != buffer) + return ptr - buffer; + else if (flags & O_NONBLOCK) + return -EWOULDBLOCK; + else + return -EIO; +} + +#else /* !ALTERA_AVALON_JTAG_UART_SMALL */ + +/* ----------------------------------------------------------- */ +/* ----------------------- FAST DRIVER ----------------------- */ +/* ----------------------------------------------------------- */ + +int +altera_avalon_jtag_uart_read(altera_avalon_jtag_uart_state* sp, + char * buffer, int space, int flags) +{ + char * ptr = buffer; + + alt_irq_context context; + unsigned int n; + + /* + * When running in a multi threaded environment, obtain the "read_lock" + * semaphore. This ensures that reading from the device is thread-safe. + */ + ALT_SEM_PEND (sp->read_lock, 0); + + while (space > 0) + { + unsigned int in, out; + + /* Read as much data as possible */ + do + { + in = sp->rx_in; + out = sp->rx_out; + + if (in >= out) + n = in - out; + else + n = ALTERA_AVALON_JTAG_UART_BUF_LEN - out; + + if (n == 0) + break; /* No more data available */ + + if (n > space) + n = space; + + memcpy(ptr, sp->rx_buf + out, n); + ptr += n; + space -= n; + + sp->rx_out = (out + n) % ALTERA_AVALON_JTAG_UART_BUF_LEN; + } + while (space > 0); + + /* If we read any data then return it */ + if (ptr != buffer) + break; + + /* If in non-blocking mode then return error */ + if (flags & O_NONBLOCK) + break; + +#ifdef __ucosii__ + /* OS Present: Pend on a flag if the OS is running, otherwise spin */ + if(OSRunning == OS_TRUE) { + /* + * When running in a multi-threaded mode, we pend on the read event + * flag set and timeout event flag set in the isr. This avoids wasting CPU + * cycles waiting in this thread, when we could be doing something more + * profitable elsewhere. + */ + ALT_FLAG_PEND (sp->events, + ALT_JTAG_UART_READ_RDY | ALT_JTAG_UART_TIMEOUT, + OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME, + 0); + } + else { + /* Spin until more data arrives or until host disconnects */ + while (in == sp->rx_in && sp->host_inactive < sp->timeout) + ; + } +#else + /* No OS: Always spin */ + while (in == sp->rx_in && sp->host_inactive < sp->timeout) + ; +#endif /* __ucosii__ */ + + if (in == sp->rx_in) + break; + } + + /* + * Now that access to the circular buffer is complete, release the read + * semaphore so that other threads can access the buffer. + */ + + ALT_SEM_POST (sp->read_lock); + + if (ptr != buffer) + { + /* If we read any data then there is space in the buffer so enable interrupts */ + context = alt_irq_disable_all(); + sp->irq_enable |= ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK; + IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable); + alt_irq_enable_all(context); + } + + if (ptr != buffer) + return ptr - buffer; + else if (flags & O_NONBLOCK) + return -EWOULDBLOCK; + else + return -EIO; +} + +#endif /* ALTERA_AVALON_JTAG_UART_SMALL */ diff --git a/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_write.c b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_write.c new file mode 100644 index 0000000..cf41ba8 --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/altera_avalon_jtag_uart_write.c @@ -0,0 +1,217 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "sys/alt_irq.h" +#include "sys/alt_alarm.h" +#include "sys/ioctl.h" +#include "alt_types.h" + +#include "altera_avalon_jtag_uart_regs.h" +#include "altera_avalon_jtag_uart.h" + +#include "sys/alt_log_printf.h" + +#ifdef __ucosii__ +#include "includes.h" +#endif /* __ucosii__ */ + +#ifdef ALTERA_AVALON_JTAG_UART_SMALL + +/* ----------------------------------------------------------- */ +/* ------------------------ SMALL DRIVER --------------------- */ +/* ----------------------------------------------------------- */ + +/* Write routine. The small version blocks when there is no space to write + * into, so it's performance will be very bad if you are writing more than + * one FIFOs worth of data. But you said you didn't want to use interrupts :-) + */ + +int altera_avalon_jtag_uart_write(altera_avalon_jtag_uart_state* sp, + const char * ptr, int count, int flags) +{ + unsigned int base = sp->base; + + const char * end = ptr + count; + + while (ptr < end) + if ((IORD_ALTERA_AVALON_JTAG_UART_CONTROL(base) & ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK) != 0) + IOWR_ALTERA_AVALON_JTAG_UART_DATA(base, *ptr++); + + return count; +} + +#else /* !ALTERA_AVALON_JTAG_UART_SMALL */ + +/* ----------------------------------------------------------- */ +/* ------------------------- FAST DRIVER --------------------- */ +/* ----------------------------------------------------------- */ + +int +altera_avalon_jtag_uart_write(altera_avalon_jtag_uart_state* sp, + const char * ptr, int count, int flags) +{ + /* Remove warning at optimisation level 03 by seting out to 0 */ + unsigned int in, out=0; + unsigned int n; + alt_irq_context context; + + const char * start = ptr; + + /* + * When running in a multi threaded environment, obtain the "write_lock" + * semaphore. This ensures that writing to the device is thread-safe. + */ + ALT_SEM_PEND (sp->write_lock, 0); + + do + { + /* Copy as much as we can into the transmit buffer */ + while (count > 0) + { + /* We need a stable value of the out pointer to calculate the space available */ + in = sp->tx_in; + out = sp->tx_out; + + if (in < out) + n = out - 1 - in; + else if (out > 0) + n = ALTERA_AVALON_JTAG_UART_BUF_LEN - in; + else + n = ALTERA_AVALON_JTAG_UART_BUF_LEN - 1 - in; + + if (n == 0) + break; + + if (n > count) + n = count; + + memcpy(sp->tx_buf + in, ptr, n); + ptr += n; + count -= n; + + sp->tx_in = (in + n) % ALTERA_AVALON_JTAG_UART_BUF_LEN; + } + + /* + * If interrupts are disabled then we could transmit here, we only need + * to enable interrupts if there is no space left in the FIFO + * + * For now kick the interrupt routine every time to make it transmit + * the data + */ + context = alt_irq_disable_all(); + sp->irq_enable |= ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK; + IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable); + alt_irq_enable_all(context); + + /* + * If there is any data left then either return now or block until + * some has been sent + */ + /* consider: test whether there is anything there while doing this and delay for at most 2s. */ + if (count > 0) + { + if (flags & O_NONBLOCK) + break; + +#ifdef __ucosii__ + /* OS Present: Pend on a flag if the OS is running, otherwise spin */ + if(OSRunning == OS_TRUE) { + /* + * When running in a multi-threaded mode, we pend on the write event + * flag set or the timeout flag in the isr. This avoids wasting CPU + * cycles waiting in this thread, when we could be doing something + * more profitable elsewhere. + */ +#ifdef ALTERA_AVALON_JTAG_UART_IGNORE_FIFO_FULL_ERROR + if(!sp->host_inactive) +#endif + ALT_FLAG_PEND (sp->events, + ALT_JTAG_UART_WRITE_RDY | ALT_JTAG_UART_TIMEOUT, + OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME, + 0); + } + else { + /* + * OS not running: Wait for data to be removed from buffer. + * Once the interrupt routine has removed some data then we + * will be able to insert some more. + */ + while (out == sp->tx_out && sp->host_inactive < sp->timeout) + ; + } +#else + /* + * No OS present: Always wait for data to be removed from buffer. Once + * the interrupt routine has removed some data then we will be able to + * insert some more. + */ + while (out == sp->tx_out && sp->host_inactive < sp->timeout) + ; +#endif /* __ucosii__ */ + + if (sp->host_inactive) + break; + } + } + while (count > 0); + + /* + * Now that access to the circular buffer is complete, release the write + * semaphore so that other threads can access the buffer. + */ + ALT_SEM_POST (sp->write_lock); + + if (ptr != start) + return ptr - start; + else if (flags & O_NONBLOCK) + return -EWOULDBLOCK; +#ifdef ALTERA_AVALON_JTAG_UART_IGNORE_FIFO_FULL_ERROR + else if (sp->host_inactive >= sp->timeout) { + /* + * Reset the software FIFO, hardware FIFO could not be reset. + * Just throw away characters without reporting error. + */ + sp->tx_out = sp->tx_in = 0; + return ptr - start + count; + } +#endif + else + return -EIO; /* Host not connected */ +} + +#endif /* ALTERA_AVALON_JTAG_UART_SMALL */ diff --git a/software/sys_controller_bsp/drivers/src/altera_epcq_controller_mod.c b/software/sys_controller_bsp/drivers/src/altera_epcq_controller_mod.c new file mode 100644 index 0000000..5147a95 --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/altera_epcq_controller_mod.c @@ -0,0 +1,797 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2015 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* * +******************************************************************************/ + +#include +#include +#include +#include +#include "sys/param.h" +#include "alt_types.h" +#include "altera_epcq_controller_mod_regs.h" +#include "altera_epcq_controller_mod.h" +#include "priv/alt_busy_sleep.h" +#include "sys/alt_debug.h" +#include "sys/alt_cache.h" + + +ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments(alt_epcq_controller_dev *flash_info,alt_u32 offset, alt_u32 length); +alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info); + +/* + * Public API + * + * Refer to “Using Flash Devices” in the + * Developing Programs Using the Hardware Abstraction Layer chapter + * of the Nios II Software Developer’s Handbook. + */ + + + /** + * alt_epcq_controller_lock + * + * Locks the range of the memory sectors, which + * protected from write and erase. + * + * Arguments: + * - *flash_info: Pointer to general flash device structure. + * - sectors_to_lock: Block protection bits in EPCQ ==> Bit4 | Bit3 | Bit2 | Bit1 | Bit0 + * TB | BP3 | BP2 | BP1 | BP0 + * For details of setting sectors protection, please refer to EPCQ datasheet. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -ETIME -> Time out and skipping the looping after 0.7 sec. + * -ENOLCK -> Sectors lock failed. +**/ +int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock) +{ + alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */ + alt_epcq_controller_dev* epcq_flash_info = NULL; + alt_u32 result = 0; + alt_32 status = 0; + + /* return -EINVAL if flash_info is NULL */ + if(NULL == flash_info || 0 > sectors_to_lock) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* sector value should occupy bits 17:8 */ + mem_op_value = sectors_to_lock << 8; + + /* sector protect commands 0b11 occupies lower 2 bits */ + mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD; + + /* write sector protect command to EPCQ_MEM_OP register to protect sectors */ + IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value); + + /* poll write in progress to make sure no operation is in progress */ + status = alt_epcq_poll_for_write_in_progress(epcq_flash_info); + if(status != 0) + { + return status; + } + + status = IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base); + result |= (status >> 2) & 0x07; /* extract out BP3 - BP0 */ + result |= (status >> 3) & 0x08; /* extract out BP4 */ + result |= (status >> 1) & 0x10; /* extract out TOP/BOTTOM bit */ + + if(result != sectors_to_lock) + { + return -ENOLCK; + } + + return 0; +} + +/** + * alt_epcq_controller_get_info + * + * Pass the table of erase blocks to the user. This flash will return a single + * flash_region that gives the number and size of sectors for the device used. + * + * Arguments: + * - *fd: Pointer to general flash device structure. + * - **info: Pointer to flash region + * - *number_of_regions: Pointer to number of regions + * + * For details of setting sectors protection, please refer to EPCQ datasheet. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> Could be hardware problem. +**/ +int alt_epcq_controller_get_info +( + alt_flash_fd *fd, /** flash device descriptor */ + flash_region **info, /** pointer to flash_region will be stored here */ + int *number_of_regions /** number of regions will be stored here */ +) +{ + alt_flash_dev* flash = NULL; + + /* return -EINVAL if fd,info and number_of_regions are NULL */ + if(NULL == fd || NULL == info || NULL == number_of_regions) + { + return -EINVAL; + } + + flash = (alt_flash_dev*)fd; + + *number_of_regions = flash->number_of_regions; + + if (!flash->number_of_regions) + { + return -EIO; + } + else + { + *info = &flash->region_info[0]; + } + + return 0; +} + +/** + * alt_epcq_controller_erase_block + * + * This function erases a single flash sector. + * + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - block_offset: byte-addressed offset, from start of flash, of the sector to be erased + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> write failed, sector might be protected +**/ +int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset) +{ + alt_32 ret_code = 0; + alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */ + alt_epcq_controller_dev* epcq_flash_info = NULL; + alt_u32 sector_number = 0; + + /* return -EINVAL if flash_info is NULL */ + if(NULL == flash_info) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* + * Sanity checks that block_offset is within the flash memory span and that the + * block offset is sector aligned. + * + */ + if((block_offset < 0) + || (block_offset >= epcq_flash_info->size_in_bytes) + || (block_offset & (epcq_flash_info->sector_size - 1)) != 0) + { + return -EINVAL; + } + + /* calculate current sector/block number */ + sector_number = (block_offset/(epcq_flash_info->sector_size)); + + /* sector value should occupy bits 23:8 */ + mem_op_value = (sector_number << 8) & ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK; + + /* sector erase commands 0b10 occupies lower 2 bits */ + mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD; + + /* write sector erase command to EPCQ_MEM_OP register to erase sector "sector_number" */ + IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value); + + /* check whether erase triggered a illegal erase interrupt */ + if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) & + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK) == + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE) + { + /* clear register */ + /* EPCQ_ISR access is write one to clear (W1C) */ + IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base, + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK ); + return -EIO; /* erase failed, sector might be protected */ + } + + return ret_code; +} + +/** + * alt_epcq_controller_write_block + * + * This function writes one block/sector of data to flash. The length of the write can NOT + * spill into the adjacent sector. + * + * It assumes that someone has already erased the appropriate sector(s). + * + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - block_offset: byte-addressed offset, from the start of flash, of the sector to written to + * - data-offset: Byte offset (unaligned access) of write into flash memory. + * For best performance, word(32 bits - aligned access) offset of write is recommended. + * - *src_addr: source buffer + * - length: size of writing + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> write failed, sector might be protected +**/ +int alt_epcq_controller_write_block +( + alt_flash_dev *flash_info, /** flash device info */ + int block_offset, /** sector/block offset in byte addressing */ + int data_offset, /** offset of write from base address */ + const void *data, /** data to be written */ + int length /** bytes of data to be written, >0 */ +) +{ + alt_u32 buffer_offset = 0; /** offset into data buffer to get write data */ + alt_u32 remaining_length = length; /** length left to write */ + alt_u32 write_offset = data_offset; /** offset into flash to write too */ + + alt_epcq_controller_dev *epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* + * Sanity checks that data offset is not larger then a sector, that block offset is + * sector aligned and within the valid flash memory range and a write doesn't spill into + * the adjacent flash sector. + */ + if(block_offset < 0 + || data_offset < 0 + || NULL == flash_info + || NULL == data + || data_offset >= epcq_flash_info->size_in_bytes + || block_offset >= epcq_flash_info->size_in_bytes + || length > (epcq_flash_info->sector_size - (data_offset - block_offset)) + || length < 0 + || (block_offset & (epcq_flash_info->sector_size - 1)) != 0) + { + return -EINVAL; + } + + /* + * Do writes one 32-bit word at a time. + * We need to make sure that we pad the first few bytes so they're word aligned if they are + * not already. + */ + while (remaining_length > 0) + { + alt_u32 word_to_write = 0xFFFFFFFF; /** initialize word to write to blank word */ + alt_u32 padding = 0; /** bytes to pad the next word that is written */ + alt_u32 bytes_to_copy = sizeof(alt_u32); /** number of bytes from source to copy */ + + /* + * we need to make sure the write is word aligned + * this should only be true at most 1 time + */ + if (0 != (write_offset & (sizeof(alt_u32) - 1))) + { + /* + * data is not word aligned + * calculate padding bytes need to add before start of a data offset + */ + padding = write_offset & (sizeof(alt_u32) - 1); + + /* update variables to account for padding being added */ + bytes_to_copy -= padding; + + if(bytes_to_copy > remaining_length) + { + bytes_to_copy = remaining_length; + } + + write_offset = write_offset - padding; + if(0 != (write_offset & (sizeof(alt_u32) - 1))) + { + return -EINVAL; + } + } + else + { + if(bytes_to_copy > remaining_length) + { + bytes_to_copy = remaining_length; + } + } + + /* prepare the word to be written */ + memcpy((((void*)&word_to_write)) + padding, ((void*)data) + buffer_offset, bytes_to_copy); + + /* update offset and length variables */ + buffer_offset += bytes_to_copy; + remaining_length -= bytes_to_copy; + + /* write to flash 32 bits at a time */ + IOWR_32DIRECT(epcq_flash_info->data_base, write_offset, word_to_write); + + /* check whether write triggered a illegal write interrupt */ + if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) & + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK) == + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE) + { + /* clear register */ + IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base, + ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK ); + return -EIO; /** write failed, sector might be protected */ + } + + /* update current offset */ + write_offset = write_offset + sizeof(alt_u32); + } + + return 0; +} + +/** + * alt_epcq_controller_write + * + * Program the data into the flash at the selected address. + * + * The different between this function and alt_epcq_controller_write_block function + * is that this function (alt_epcq_controller_write) will automatically erase a block as needed + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - offset: Byte offset (unaligned access) of write to flash memory. For best performance, + * word(32 bits - aligned access) offset of write is recommended. + * - *src_addr: source buffer + * - length: size of writing + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -EIO -> write failed, sector might be protected + * +**/ +int alt_epcq_controller_write( + alt_flash_dev *flash_info, /** device info */ + int offset, /** offset of write from base address */ + const void *src_addr, /** source buffer */ + int length /** size of writing */ +) +{ + alt_32 ret_code = 0; + + alt_epcq_controller_dev *epcq_flash_info = NULL; + + alt_u32 write_offset = offset; /** address of next byte to write */ + alt_u32 remaining_length = length; /** length of write data left to be written */ + alt_u32 buffer_offset = 0; /** offset into source buffer to get write data */ + alt_u32 i = 0; + + /* return -EINVAL if flash_info and src_addr are NULL */ + if(NULL == flash_info || NULL == src_addr) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* make sure the write parameters are within the bounds of the flash */ + ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length); + + if(0 != ret_code) + { + return ret_code; + } + + /* + * This loop erases and writes data one sector at a time. We check for write completion + * before starting the next sector. + */ + for(i = offset/epcq_flash_info->sector_size ; i < epcq_flash_info->number_of_sectors; i++) + { + alt_u32 block_offset = 0; /** block offset in byte addressing */ + alt_u32 offset_within_current_sector = 0; /** offset into current sector to write */ + alt_u32 length_to_write = 0; /** length to write to current sector */ + + if(0 >= remaining_length) + { + break; /* out of data to write */ + } + + /* calculate current sector/block offset in byte addressing */ + block_offset = write_offset & ~(epcq_flash_info->sector_size - 1); + + /* calculate offset into sector/block if there is one */ + if(block_offset != write_offset) + { + offset_within_current_sector = write_offset - block_offset; + } + + /* erase sector */ + ret_code = alt_epcq_controller_erase_block(flash_info, block_offset); + + if(0 != ret_code) + { + return ret_code; + } + + /* calculate the byte size of data to be written in a sector */ + length_to_write = MIN(epcq_flash_info->sector_size - offset_within_current_sector, + remaining_length); + + /* write data to erased block */ + ret_code = alt_epcq_controller_write_block(flash_info, block_offset, write_offset, + src_addr + buffer_offset, length_to_write); + + + if(0 != ret_code) + { + return ret_code; + } + + /* update remaining length and buffer_offset pointer */ + remaining_length -= length_to_write; + buffer_offset += length_to_write; + write_offset += length_to_write; + } + + return ret_code; +} + +/** + * alt_epcq_controller_read + * + * There's no real need to use this function as opposed to using memcpy directly. It does + * do some sanity checks on the bounds of the read. + * + * Arguments: + * - *flash_info: Pointer to general flash device structure. + * - offset: offset read from flash memory. + * - *dest_addr: destination buffer + * - length: size of reading + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments +**/ +int alt_epcq_controller_read +( + alt_flash_dev *flash_info, /** device info */ + int offset, /** offset of read from base address */ + void *dest_addr, /** destination buffer */ + int length /** size of read */ +) +{ + alt_32 ret_code = 0; + alt_epcq_controller_dev *epcq_flash_info = NULL; + + /* return -EINVAL if flash_info and dest_addr are NULL */ + if(NULL == flash_info || NULL == dest_addr) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + /* validate arguments */ + ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length); + + /* copy data from flash to destination address */ + if(0 == ret_code) + { + memcpy(dest_addr, (alt_u8*)epcq_flash_info->data_base + offset, length); + } + + return ret_code; +} + +/** + * altera_epcq_controller_init + * + * alt_sys_init.c will call this function automatically through macro + * + * Information in system.h is checked against expected values that are determined by the silicon_id. + * If the information doesn't match then this system is configured incorrectly. Most likely the wrong + * type of EPCS or EPCQ device was selected when instantiating the soft IP. + * + * Arguments: + * - *flash: Pointer to EPCQ flash device structure. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments. + * -ENODEV -> System is configured incorrectly. +**/ +alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *flash) +{ + alt_u32 silicon_id = 0; + alt_u32 size_in_bytes = 0; + alt_u32 number_of_sectors = 0; + + /* return -EINVAL if flash is NULL */ + if(NULL == flash) + { + return -EINVAL; + } + + /* return -ENODEV if CSR slave is not attached */ + if(NULL == (void *)flash->csr_base) + { + return -ENODEV; + } + + + /* + * If flash is an EPCQ device, we read the EPCQ_RD_RDID register for the ID + * If flash is an EPCS device, we read the EPCQ_RD_SID register for the ID + * + * Whether or not the flash is a EPCQ or EPCS is indicated in the system.h. The system.h gets + * this value from the hw.tcl of the IP. If this value is set incorrectly, then things will go + * badly. + * + * In both cases, we can determine the number of sectors, which we can use + * to calculate a size. We compare that size to the system.h value to make sure + * the EPCQ soft IP was configured correctly. + */ + if(0 == flash->is_epcs) + { + /* If we're an EPCQ, we read EPCQ_RD_RDID for the silicon ID */ + silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_RDID(flash->csr_base); + silicon_id &= ALTERA_EPCQ_CONTROLLER_RDID_MASK; + + /* Determine which EPCQ device so we can figure out the number of sectors */ + /* EPCQ share the same ID for the same capacity*/ + switch(silicon_id) + { + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16: + { + number_of_sectors = 32; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32: + { + number_of_sectors = 64; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64: + { + number_of_sectors = 128; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128: + { + number_of_sectors = 256; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256: + { + number_of_sectors = 512; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512: + { + number_of_sectors = 1024; + break; + } + case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024: + { + number_of_sectors = 2048; + break; + } + default: + { + return -ENODEV; + } + } + } + else { + /* If we're an EPCS, we read EPCQ_RD_SID for the silicon ID */ + silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_SID(flash->csr_base); + silicon_id &= ALTERA_EPCQ_CONTROLLER_SID_MASK; + + /* Determine which EPCS device so we can figure out various properties */ + switch(silicon_id) + { + case ALTERA_EPCQ_CONTROLLER_SID_EPCS16: + { + number_of_sectors = 32; + break; + } + case ALTERA_EPCQ_CONTROLLER_SID_EPCS64: + { + number_of_sectors = 128; + break; + } + case ALTERA_EPCQ_CONTROLLER_SID_EPCS128: + { + number_of_sectors = 256; + break; + } + default: + { + return -ENODEV; + } + } + } + + /* Calculate size of flash based on number of sectors */ + size_in_bytes = number_of_sectors * flash->sector_size; + + /* + * Make sure calculated size is the same size given in system.h + * Also check number of sectors is the same number given in system.h + * Otherwise the EPCQ IP was not configured correctly + */ + if( size_in_bytes != flash->size_in_bytes || + number_of_sectors != flash->number_of_sectors) + { + flash->dev.number_of_regions = 0; + return -ENODEV; + } + else + { + flash->silicon_id = silicon_id; + flash->number_of_sectors = number_of_sectors; + + /* + * populate fields of region_info required to conform to HAL API + * create 1 region that composed of "number_of_sectors" blocks + */ + flash->dev.number_of_regions = 1; + flash->dev.region_info[0].offset = 0; + flash->dev.region_info[0].region_size = size_in_bytes; + flash->dev.region_info[0].number_of_blocks = number_of_sectors; + flash->dev.region_info[0].block_size = flash->sector_size; + } + + + /* + * Register this device as a valid flash device type + * + * Only register the device if it's configured correctly. + */ + alt_flash_device_register(&(flash->dev)); + + + return 0; +} + + +/* + * Private API + * + * Helper functions used by Public API functions. + * + * Arguments: + * - *flash_info: Pointer to EPCQ flash device structure. + * - offset: Offset of read/write from base address. + * - length: Length of read/write in bytes. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + */ +/** + * Used to check that arguments to a read or write are valid + */ +ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments +( + alt_epcq_controller_dev *flash_info, /** device info */ + alt_u32 offset, /** offset of read/write */ + alt_u32 length /** length of read/write */ +) +{ + alt_epcq_controller_dev *epcq_flash_info = NULL; + alt_u32 start_address = 0; + alt_32 end_address = 0; + + /* return -EINVAL if flash_info is NULL */ + if(NULL == flash_info) + { + return -EINVAL; + } + + epcq_flash_info = (alt_epcq_controller_dev*)flash_info; + + start_address = epcq_flash_info->data_base + offset; /** first address of read or write */ + end_address = start_address + length; /** last address of read or write (not inclusive) */ + + /* make sure start and end address is less then the end address of the flash */ + if( + start_address >= epcq_flash_info->data_end || + end_address >= epcq_flash_info->data_end || + offset < 0 || + length < 0 + ) + { + return -EINVAL; + } + + return 0; +} + +/* + * Private function that polls write in progress bit EPCQ_RD_STATUS. + * + * Write in progress will be set if any of the following operations are in progress: + * -WRITE STATUS REGISTER + * -WRITE NONVOLATILE CONFIGURATION REGISTER + * -PROGRAM + * -ERASE + * + * Assumes EPCQ was configured correctly. + * + * If ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE is set, the function will time out after + * a period of time determined by that value. + * + * Arguments: + * - *epcq_flash_info: Pointer to EPCQ flash device structure. + * + * Returns: + * 0 -> success + * -EINVAL -> Invalid arguments + * -ETIME -> Time out and skipping the looping after 0.7 sec. + */ +alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info) +{ + /* we'll want to implement timeout if a timeout value is specified */ +#if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0 + alt_u32 timeout = ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE; + alt_u16 counter = 0; +#endif + + /* return -EINVAL if epcq_flash_info is NULL */ + if(NULL == epcq_flash_info) + { + return -EINVAL; + } + + /* while Write in Progress bit is set, we wait */ + while((IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base) & + ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK) == + ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY) + { + alt_busy_sleep(1); /* delay 1us */ +#if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0 + if(timeout <= counter ) + { + return -ETIME; + } + + counter++; +#endif + + } + + return 0; +} + + diff --git a/software/sys_controller_bsp/drivers/src/ci_crc.c b/software/sys_controller_bsp/drivers/src/ci_crc.c new file mode 100644 index 0000000..7f9b0f0 --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/ci_crc.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/********************************************************************** + * + * Filename: ci_crc.c + * + * Description: Custom instruction implementations of the CRC. + * + * Notes: A macro is defined that is used to access the CRC custom + * instruction. + *********************************************************************/ + +#include "system.h" + +/*The n values and their corresponding operation are as follow: + * n = 0, Initialize the custom instruction to the initial remainder value + * n = 1, Write 8 bits data to custom instruction + * n = 2, Write 16 bits data to custom instruction + * n = 3, Write 32 bits data to custom instruction + * n = 4, Read 32 bits data from the custom instruction + * n = 5, Read 64 bits data from the custom instruction + * n = 6, Read 96 bits data from the custom instruction + * n = 7, Read 128 bits data from the custom instruction*/ +#define CRC_CI_MACRO(n, A) __builtin_custom_ini(ALT_CI_NIOS2_HW_CRC32_0_N + (n & 0x7), (A)) + +unsigned long crcCI(unsigned char * input_data, unsigned long input_data_length, int do_initialize) +{ + unsigned long index; + /* copy of the data buffer pointer so that it can advance by different widths */ + void * input_data_copy = (void *)input_data; + + /* The custom instruction CRC will initialize to the inital remainder value */ + if (do_initialize) + CRC_CI_MACRO(0,0); + + /* Write 32 bit data to the custom instruction. If the buffer does not end + * on a 32 bit boundary then the remaining data will be sent to the custom + * instruction in the 'if' statement below. + */ + for(index = 0; index < (input_data_length & 0xFFFFFFFC); index+=4) + { + CRC_CI_MACRO(3, *(unsigned long *)input_data_copy); + input_data_copy += 4; /* void pointer, must move by 4 for each word */ + } + + /* Write the remainder of the buffer if it does not end on a word boundary */ + if((input_data_length & 0x3) == 0x3) /* 3 bytes left */ + { + CRC_CI_MACRO(2, *(unsigned short *)input_data_copy); + input_data_copy += 2; + CRC_CI_MACRO(1, *(unsigned char *)input_data_copy); + } + else if((input_data_length & 0x3) == 0x2) /* 2 bytes left */ + { + CRC_CI_MACRO(2, *(unsigned short *)input_data_copy); + } + else if((input_data_length & 0x3) == 0x1) /* 1 byte left */ + { + CRC_CI_MACRO(1, *(unsigned char *)input_data_copy); + } + + /* There are 4 registers in the CRC custom instruction. Since + * this example uses CRC-32 only the first register must be read + * in order to receive the full result. + */ + return CRC_CI_MACRO(4, 0); +} diff --git a/software/sys_controller_bsp/drivers/src/crc.c b/software/sys_controller_bsp/drivers/src/crc.c new file mode 100644 index 0000000..f00568d --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/crc.c @@ -0,0 +1,265 @@ +/****************************************************************************** +* * +* License Agreement * +* * +* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * +* All rights reserved. * +* * +* Permission is hereby granted, free of charge, to any person obtaining a * +* copy of this software and associated documentation files (the "Software"), * +* to deal in the Software without restriction, including without limitation * +* the rights to use, copy, modify, merge, publish, distribute, sublicense, * +* and/or sell copies of the Software, and to permit persons to whom the * +* Software is furnished to do so, subject to the following conditions: * +* * +* The above copyright notice and this permission notice shall be included in * +* all copies or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +* DEALINGS IN THE SOFTWARE. * +* * +* This agreement shall be governed in all respects by the laws of the State * +* of California and by the laws of the United States of America. * +* Altera does not recommend, suggest or require that this reference design * +* file be used in conjunction or combination with any other product. * +******************************************************************************/ + + +/********************************************************************** + * + * Filename: crc.c + * + * Description: Slow and fast implementations of the CRC standards. + * + * Notes: The parameters for each supported CRC standard are + * defined in the header file crc.h. The implementations + * here should stand up to further additions to that list. + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#include "crc.h" + + +/* + * Derive parameters from the standard-specific parameters in crc.h. + */ +#define WIDTH (8 * sizeof(crc)) +#define TOPBIT (1 << (WIDTH - 1)) + +#if (REFLECT_DATA == TRUE) +#undef REFLECT_DATA +#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8)) +#else +#undef REFLECT_DATA +#define REFLECT_DATA(X) (X) +#endif + +#if (REFLECT_REMAINDER == TRUE) +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH)) +#else +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) (X) +#endif + + +/********************************************************************* + * + * Function: reflect() + * + * Description: Reorder the bits of a binary sequence, by reflecting + * them about the middle position. + * + * Notes: No checking is done that nBits <= 32. + * + * Returns: The reflection of the original data. + * + *********************************************************************/ +static unsigned long +reflect(unsigned long data, unsigned char nBits) +{ + unsigned long reflection = 0x00000000; + unsigned char bit; + + /* + * Reflect the data about the center bit. + */ + for (bit = 0; bit < nBits; ++bit) + { + /* + * If the LSB bit is set, set the reflection of it. + */ + if (data & 0x01) + { + reflection |= (1 << ((nBits - 1) - bit)); + } + + data = (data >> 1); + } + + return (reflection); + +} /* reflect() */ + + +/********************************************************************* + * + * Function: crcSlow() + * + * Description: Compute the CRC of a given message. + * + * Notes: + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcSlow(unsigned char const message[], int nBytes) +{ + crc remainder = INITIAL_REMAINDER; + int byte; + unsigned char bit; + + + /* + * Perform modulo-2 division, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) + { + /* + * Bring the next byte into the remainder. + */ + remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8)); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) + { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) + { + remainder = (remainder << 1) ^ POLYNOMIAL; + } + else + { + remainder = (remainder << 1); + } + } + } + + /* + * The final remainder is the CRC result. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcSlow() */ + + +crc crcTable[256]; + + +/********************************************************************* + * + * Function: crcInit() + * + * Description: Populate the partial CRC lookup table. + * + * Notes: This function must be rerun any time the CRC standard + * is changed. If desired, it can be run "offline" and + * the table results stored in an embedded system's ROM. + * + * Returns: None defined. + * + *********************************************************************/ +void +crcInit(void) +{ + crc remainder; + int dividend; + unsigned char bit; + + + /* + * Compute the remainder of each possible dividend. + */ + for (dividend = 0; dividend < 256; ++dividend) + { + /* + * Start with the dividend followed by zeros. + */ + remainder = dividend << (WIDTH - 8); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) + { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) + { + remainder = (remainder << 1) ^ POLYNOMIAL; + } + else + { + remainder = (remainder << 1); + } + } + + /* + * Store the result into the table. + */ + crcTable[dividend] = remainder; + } + +} /* crcInit() */ + + +/********************************************************************* + * + * Function: crcFast() + * + * Description: Compute the CRC of a given message. + * + * Notes: crcInit() must be called first. + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcFast(unsigned char const message[], int nBytes) +{ + crc remainder = INITIAL_REMAINDER; + unsigned char data; + int byte; + + + /* + * Divide the message by the polynomial, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) + { + data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)); + remainder = crcTable[data] ^ (remainder << 8); + } + + /* + * The final remainder is the CRC. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcFast() */ diff --git a/software/sys_controller_bsp/drivers/src/i2c_opencores.c b/software/sys_controller_bsp/drivers/src/i2c_opencores.c new file mode 100644 index 0000000..fafa66b --- /dev/null +++ b/software/sys_controller_bsp/drivers/src/i2c_opencores.c @@ -0,0 +1,206 @@ + +#include "alt_types.h" +#include "i2c_opencores_regs.h" +#include "i2c_opencores.h" + +// #define I2C_DEBUG +//int I2C_init(alt_u32 base,alt_u32 clk, alt_u32 speed) +//int I2C_start(alt_u32 base, alt_u32 add, alt_u32 write); +//alt_u32 I2C_read(alt_u32 base); +//int I2C_write(alt_u32 base, alt_u8 data); +//int I2C_stop(alt_u32 base); + +/* these functions are polled only. */ +/* all functions wait until the I2C is done before exiting */ + + +/**************************************************************** +int I2C_init + This function inititlizes the prescalor for the scl + and then enables the core. This must be run before + any other i2c code is executed +inputs + base = the base address of the component + clk = freuqency of the clock driving this component ( in Hz) + speed = SCL speed ie 100K, 400K ... (in Hz) +15-OCT-07 initial release +*****************************************************************/ +void I2C_init(alt_u32 base,alt_u32 clk,alt_u32 speed) +{ + alt_u32 prescale = (clk/( 5 * speed))-1; +#ifdef I2C_DEBUG + printf(" Initializing I2C at 0x%x, \n\twith clock speed 0x%x \n\tand SCL speed 0x%x \n\tand prescale 0x%x\n",base,clk,speed,prescale); +#endif + IOWR_I2C_OPENCORES_CTR(base, 0x00); /* turn off the core*/ + + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_IACK_MSK); /* clearn any pening IRQ*/ + + IOWR_I2C_OPENCORES_PRERLO(base, (0xff & prescale)); /* load low presacle bit*/ + + IOWR_I2C_OPENCORES_PRERHI(base, (0xff & (prescale>>8))); /* load upper prescale bit */ + + IOWR_I2C_OPENCORES_CTR(base, I2C_OPENCORES_CTR_EN_MSK); /* turn on the core*/ + +} + +/**************************************************************** +int I2C_start + Sets the start bit and then sends the first byte which + is the address of the device + the write bit. +inputs + base = the base address of the component + add = address of I2C device + read = 1== read 0== write +return value + 0 if address is acknowledged + 1 if address was not acknowledged +15-OCT-07 initial release +*****************************************************************/ +int I2C_start(alt_u32 base, alt_u32 add, alt_u32 read) +{ +#ifdef I2C_DEBUG + printf(" Start I2C at 0x%x, \n\twith address 0x%x \n\tand read 0x%x \n\tand prescale 0x%x\n",base,add,read); +#endif + + /* transmit the address shifted by one and the read/write bit*/ + IOWR_I2C_OPENCORES_TXR(base, ((add<<1) + (0x1 & read))); + + /* set start and write bits which will start the transaction*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_STA_MSK | I2C_OPENCORES_CR_WR_MSK ); + + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now check to see if the address was acknowledged */ + if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK) + { +#ifdef I2C_DEBUG + printf("\tNOACK\n"); +#endif + return (I2C_NOACK); + } + else + { +#ifdef I2C_DEBUG + printf("\tACK\n"); +#endif + return (I2C_ACK); + } +} + +/**************************************************************** +int I2C_read + assumes that any addressing and start + has already been done. + reads one byte of data from the slave. on the last read + we don't acknowldge and set the stop bit. +inputs + base = the base address of the component + last = on the last read there must not be a ack + +return value + byte read back. +15-OCT-07 initial release +*****************************************************************/ +alt_u32 I2C_read(alt_u32 base,alt_u32 last) +{ +#ifdef I2C_DEBUG + printf(" Read I2C at 0x%x, \n\twith last0x%x\n",base,last); +#endif + if( last) + { + /* start a read and no ack and stop bit*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK | + I2C_OPENCORES_CR_NACK_MSK | I2C_OPENCORES_CR_STO_MSK); + } + else + { + /* start read*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK ); + } + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now read the data */ + return (IORD_I2C_OPENCORES_RXR(base)); + +} + +/**************************************************************** +int I2C_write + assumes that any addressing and start + has already been done. + writes one byte of data from the slave. + If last is set the stop bit set. +inputs + base = the base address of the component + data = byte to write + last = on the last read there must not be a ack + +return value + 0 if address is acknowledged + 1 if address was not acknowledged +15-OCT-07 initial release +*****************************************************************/ +alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last) +{ + #ifdef I2C_DEBUG + printf(" Read I2C at 0x%x, \n\twith data 0x%x,\n\twith last0x%x\n",base,data,last); +#endif + /* transmit the data*/ + IOWR_I2C_OPENCORES_TXR(base, data); + + if( last) + { + /* start a write with ack and stop bit*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK | + I2C_OPENCORES_CR_STO_MSK); + } + else + { + /* start write with ack */ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK ); + } + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now check to see if the address was acknowledged */ + if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK) + { +#ifdef I2C_DEBUG + printf("\tNOACK\n"); +#endif + return (I2C_NOACK); + } + else + { +#ifdef I2C_DEBUG + printf("\tACK\n"); +#endif + return (I2C_ACK); + } + +} + +alt_u32 SPI_read(alt_u32 base) +{ + /* start read*/ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK ); + + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); + + /* now read the data */ + return (IORD_I2C_OPENCORES_RXR(base)); +} + +void SPI_write(alt_u32 base,alt_u8 data) { + /* transmit the data*/ + IOWR_I2C_OPENCORES_TXR(base, data); + + /* start write */ + IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK ); + + /* wait for the trnasaction to be over.*/ + while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK); +} diff --git a/software/sys_controller_bsp/libhal_bsp.a b/software/sys_controller_bsp/libhal_bsp.a new file mode 100644 index 0000000000000000000000000000000000000000..5cac88b2f2730f1d5666703f25bd3a72ba948827 GIT binary patch literal 107610 zcmeFa4|JT@bszW!7=R!Nkpl@JAc=+s5(I)44Gcg41QFRBNw7?bkVIRQ%XPFF4uJtV z7Jz|g1`^3A>v00dNTM`It3BmO)P_x!UDlNwwpF}J>Qm3z!Zw?ucA;8HDVdhEU8P66 zQ5wZnwz4Ff`}@83?l*5f%wPr-WK(P1Ip4hd?z`XnfA9PMzK&bt>G9*A*wh;?hQ5Kp zzQM@u!NI-Za6~(~|KV`|-hmgi@dQx>BS6)ja#*C!Yf|=DGJjD)s5NmHPS5C^i27 zDE0Zt+d;{DIhD)lcAFZcPQ-&g97zp7LoVSMYjQhz$8)OX=0pa0aL)c4xV z^Ag_s&%dnHYlz$Hi2HxPPN{buE_wp0U+JgjEfwIisZ9k!$5o*DRTa4I@2bE@{zL_C zOsl}nKURV6vnsIb6%~lQs{(_~DloFB0w3R|0?}Vx`F!#}s=!@;t^#9!ssi_YTLtd_ z&nocQ|DXb&8&QE@_<;(ukanG%h)pFkCXk85!?Bq;``UE;L~L@x_yD@cG?^*j zd|`?%vE)o9VWT=R9gn3?j31BB#8R_~8RJ8N=6OWEYzaO~(|oasRBSw(N@o7CN`6TZG1d78PCQ|dOe%Nl};Q(EE8!RnZnBjR>XE<3huF3Vg_kSA$JTq zH=`|}Cex`ILo~jm(=(}J|B7v~>A9(iFs7X{c zQwfeG7`P4yD2g$yV9q8dXk?SqiPYpo{G@hICo+blZFD=8nnAK+)8nbRnJhdWPo=F_ z(5jW0Be@%7?UQJGp$C8;e<69_9($Zf*sl|`l46&4nWX4Z2Og6+) zo)v1wcziCCh#gDJB+~J0Vj^}lJ`sygOqdFkOd$>vNhB|;lBsc9dL|m#w8l}o-sv2miTx!i5h}5WV0vLLrDnbRC30+Poz+?c=WYa1w z1(!}tCE~~_TVv9R>G*6+7pBQ(LztVfBqV(%KAljRqo{ti@|gORNlj)SiKi0rveLZ&d6=ZvO( zBo6V^>XJdACd6ivsZ2ksMZd0f$r&)jkSHWYS#52Eno(dmY7Sa5Co{&9m>vH@Y&QR_DjA0vS@n0= zl*I0b9Hi2*QA+ptTpC4;kJD!Q%dE24BAt~qh z!|^Eu_W5l5SZoeqBhwHoQ^{EmR=De0vKoU(O!>EUJ@D5KuRZWPP)#RiCT$Dkt5XOB zGI_M@%O8x~`9>$M3jH;s5@r)FU+SqKv>iq_r`SJLBkX+|_@F5eFiu zx#&9()7}#?Qg{Esy9|klA*o(}_r16?zrwb6V8GIjY@#5FGC`0%sa{PgbgqQr_N+?L z*d&#tyZtMV!PiUj=!H%Z)vil+`b9!6^i?2V>60bM(kJqqgn-u3eZwQ04$4Y)_ECiD zHpHc9ZcZe9ZK}sVgEnIhEgD3s(8Lx+3jN0tEYeVV9u*p1k5p)9U6TLJsnoHUY0`wt zX%vNI8#-t|p%j|80;SNx71N|G5$ehoOry9&3|<~myH@*N|Q4Ql?K>k&p>P=yP;(WaI_F5IG`9jywuQn0I?@ULxTp-zo-tGDJ~LKrmPHm3U29e0d` zyG@aY`v!aZ!ne;QrzXOE!-G4+13i0t`Z2kXIXRt;ABCAs8}qnesKW7{Y~n;#_2~Y0 z&(Taq^{_Jl0W?`t)qfaV%(8mR&3wbuf(Jp1T@RCZ)Y@~knAZTl0T17&TO*z>YlpLj z^VSr@7LVEm0;U^OCB8oJ@SO-A0{!dMnE9g{pC&xw7hN!QqDF{VkZ@^YYQ%#@SkA!4 zxG)cxju4)WcwGM?u-pThfcPhNFuTQ`cB4%LLO5 z>ZXFTjwfn~2aGqSpFE&lH}`JiXvY%HM1<~h7dqD3TDl8vecsGM2QapqEY9-W%uEEZ ztTtKvF!0UHOu&P9Hd(y457TlERMG)`ks+%!j%=!=10J-6z`9HwuogYO73BU%Ap5{zU}Rx~TDtVbo%0X0bkJ=7@jl3X9&+6A zrETwglkz+dym{%;zInLi>X8X9ZQGCc1u65b@V^z|1Z(myQSOUN*5n<-7Vx{jKl(vy zjfuq3xnsJNGs$Vw+g!Wi2qWUmW>;_IU>A_|`1QszPc8`A!334lmeH&9(u?PqZTo|+95EW z+pRqZlX^<)9j6CAjsf)?=FKw6-99JGx8t3l)gvt1Mq~_Sm-T}9tuV<${2)w*MVz{& z+u{>2SvN?Zg2^#~o)<%RgleXue(CG;Rs+_mU)aY8{^-(6ErIC8mYV#_)Gs3oH-)!t zSK(l7R2Rj7%A-uFM}DoXYnuwUs(iRLm~ZQfr$gf}C14SMh^iyyXkaUP$OqaeM`rs<@7$)Pj&DvQ;lz+;o z0NuOA0+aSVKKpGxyCc9<9T?M6a}*Xy+y#!pa8AFK&{O#4U&kZJ3T&D;}38G&nAm602ltpNVoiFNVhysl5X+d-Fuu~Pi4I{ z)F=Fv`#p~%90GMGbG!j982cXYRi@Wrn4#sAbbEPDaE@$t(k>%pKfSsq%+3(@r8c@Sn{qrO>9PDk<5&E8waAIIvU z^k1N|oVqb#UPx{jA2^<9ww^J6y>_{19?T2~T$0+#oe$3VwHysX1qmn*a)}xlT*#OGcQavBJvZj)Z+B%GhBL^zh)*-3gm22x$HfBXS zb>Toq59Wk0HV@bTXrJl|s4(#>S=YMlaXDSfcF+YWWq&O$$LH6zO=b#nFE&q{)qLW!u0ChK5%)DbIhjSXXcE!3T)<> zwLN1dozp3roSyFM8MvJ3=aT(G_Ui;hS9O6vd6gc{t-#MZ0xW!#LE=$7geNeGa|kB8 z<*f2_Ys5oc<@O(6b^L;p*MiGD62c9UPQGR$79?Db2in_*CR7|YokaUP$OqX6+-@sD`O0BcW2!v(AzMDG=3V|m2gWk|C z`k`o}tfMSe?4K=~m4Y0?3t2~_f3l7iC7qcB7{w!VRK0z>Wf5HD6}#KZubKBn_EbHe ztqT@miM(>XjB8~<6@3n}q}R$AAI?#?Z}Q1+i8oezkSmFz_oQyt?>a`#4Y&%&m%gN|taC1TG@GcNpNUd%=RaW zseVpxH~pl$L)=v%%*(B|@ENwuUvum!^U-18G9OLZmig#m((QaSP}OMtp`U{H_6-$H zs#Ka&`B2|{sBfaIOn?vd4fP47sQ{(MFz=hbarc=P^o>LH^o@HeM-OU#TKa~8%c&qv zcvT#a^h0$>LAV9Ec8^kps!3)Ro7jsEdPBih~w_$rMr9(DX8Ds8d9?^2G>KfWMer{gF6q!4!d{kHq!pYp{(buuRyuxK7*5AKkirb|azom>k9xo^W6>{EkESeI_<` z*ZqfLF|mE}-ceWpjd-~y?x$eB}`H|x)e-OMinmZ79XUkOz`|GVb4(z{etT&S$H`5*dvnuzS zR-jIg`D)Lrz=4AY4jepK6NC>BYd;x_psPxi^{|(EXQh9=$5YdZ-syPyp}9=&9jS># zZz_`+@0Bwby*zH`9I`u_nN^><_kr+j_lNs?`UiRj`&1woXi}m2roh#K+J@^JZf>}y zFn3J7r{n6ihJ}5LjOl9o?N>|z>Zu0r*h{9zoO|(-qW zn#K`emp`74&m6<)#x(%-3p1K?YXnpF2Is#NLWjj=uAv;?4)CG5@a81S@kzVxhRb{w z5dFt~0`aJIIDukezXNqr)9J>x>oa&Hu0ZvE&qG8kh}%7|yZ)Vpe|(?*F)rdCs&0{g zPr`l*kAV1xYYvM1d)kQ~^FjPe0hf2^M>{OdL@bEgFT*Z4orYlv6R|))3BQELO~+csGhJU{ecL52Drm5q`WeOhTfo{dac^CS}{)T@JW*5Re0J?zqC-ze2 z%JU3v$gDe3%goy=$3&6~;%*m3Y+$usZ5H>wc6crp2~W zw+wiv=sZdG&U@>;tF=*N%s1LO6xKVLPhnjUp4)&oGQ$C^lZ{qL$S-R+jHB@IUE)lS z=0}+jT%O+kh-_Ywc4O6f;JuOR*KN+4;JkKY6GjD?|9vhPhz1a?=X9NTU*>Hymvwq6 zjQBE6Hd}SPb(!0A*sNc%rZRzQ*$Ez&A>St-%cRTNrPhwZ?t)G~2)pp`-Aa7ajh0VG zi~cbz0l~SpK))l_fqb17r$IM9ejRWev?v|{i62c@5{F?q2O4F5wRzar!1s&d8BFod zA!*d5ugBQP^`A1&woHH-x6@jPbL@1twKM-XFZ+3Gr$HVg<#KyS;cTj1p7Cjem3)P> z^tzX_ib~LQdgr22WfCvD=T?s6Sc!+UIVO84FE7N*NK6At;2RifI5ivk#s(^b1jIu3}@{h?cxVe59hg3 zh8rOfK)z0mnLoPm@wZVAg7zuHqW{T5py}3H?%6y88dW6Y!#FTPe))M9d>;W_K>QQC zm@a)ipIS>z^aAdWxX=>JUudaQFSOK0UufBod!eNv z|H7%rX4SG$z1XrT`eMuG+>0%Z`4?NRQr~OY68&Dw*4+16Liz8tG(}&)p0~ejxf=M@ z(U)5;DDa%Q+5XM z-v$D;o9-?m{ZUPz$bP;iaNxk$nDGd+g&Jx%-u-FKmDZ7E5f>&6izWc?M-x-3$4@V!;3`Gl zQs*+w%{(-ddSs@E#!Cx(O8CdS4BffO%bm+~{aEAl=1*&Ga~BGY`mjsA&Q5v3yEO+){KY!H@dOy``36R4nWoa3=7u<1jOy@Ah`ZL2>&`kqkr^A{QC}Y zc?YQ43<15Ghy`(b5q81p6b2vrs{)eee+GgZZVnC{7cyMVD@wTk6}amk$8ge~!^tbd z|J%M3B@yrq_;&;*{bRpa{PXvb7vSH!a2JrUXu`>ZH&GEoAYx8V_l@aa2oKwS+gt%d zI0*MYC@; znac&JMTttEoYbpX8oICHwJD+%i>Tzi4Ug=zKStat1g;~q+v zmQ|yTw&t<($C_@luZ=v`|1fczP2I$;|I8_gkM*=ce5)7xKs{I}8=zrRl=s4A~b4l`iDfd21BIc!yLH`RyU4mGs>NvJVA^8Ci| z6QNw+sirNFXSYV1wuka!1I#*@AAz|6=JolTM&aH*n!gGAgn|!l%-_^r zr%sH#@%z_q3E(b|^WRZ0BO~X3GXVG6Q;XLfAIY`1jhuV&p;L?XZ9_G=n)(jzv)&pRS-2{^v{BIybd7Q~BMYsdT^kui(Vben zdjFWpkK^u;6C(?Mc5o#3^1+eA?T_kk7rwjy)N=E|k#o=Ae`>KYa%#Elhz{om`(`g9 zu3a1X&NT-w27uSA6DH2zz58Mv>^0hcc;x(d_m3?6AD_T|W+RZ9i~5cbd#nv6`k3f3 z!ajE3-UGEaz-GEN17o#Y@5Wz0Eceo<+UxE<@EMx$ zh~~iqwQca|9w7JP!3*R99K3hzKHWEcL??{3w$L}Ft#tp?OVqk`P<<=flw;F2Sb>85 zSy#bcX1~&0+G#p#PPdXP@MXJ;KgpHupLSo6MNTmK%i#Q%tiQwJRt;-Dw_K#OIG;v5 ziihwnbTV~0bvT;>y3tO3EPex(Lf0t&#BJ8WwIeFW3mP$h!uJrYZnzC-AS7J26%y{3 zfXh4d;RX2ji$pAl+oQ0%{x!ps2xv?Pn-=l!H-XDLK-D31Sel7g5Vte13r?rw;0qJ6 zz&H|q7mpk6C>+?%Fz#YD9PPik$&za6hg zAB7}2SHPIaJSY7X9@YioloicyljQRB_7`9DP^n*n^YC_lsB*vLEt>&Gu1&w>%`JKL z_?8#j+H3M5&d)Gj_u;8gyYXLb`=+nmEpFYu!`7{K^W9^*Wtr1n;;*Wf#d`OXY*$=4 zUDF;Zw*k?YL4Vk;u$T!VZ@V0vbW{I`84$iw?TTA2)K3I|yYdall<4=>+Lit0b?;xo zodrd3I+E{xA{NBW->#f@!lkwmef%Zh@(#VA9zRLMg1GtHmFMAK1U%FStF;Vw=29mteSRZKRmCdT{(}8SVlON+LhBt?~OV}=Fg40LoPx; z2r*3zyp+;Z)T36I}yF$->$+LgU~?N;0>_G9d_ z1vh~3x$@8THaW|V@n;C*v7+)NjCY4m9>jMaPD$ zUD67xnu6svA{N9yv5V=_E3f^zA#nbYxm^IBcPpNugFz9sh8Ar1Hb~>4+(*qA%YD?WV{&emWhv)o zjc(BQ=2x}GIOJWcQMu3gq=}Ag^UYo@-jgx=#zz(Jf;~s`5>6ej_uBkAt;bWR3P|a9 zfWUerwPU|9SX1iQ4%k^|EAj0D58sL4A<(~0jhR2X@$t(LG+b5twqC`{v*6`$gZhT) zU|sW%^A17QO06}3wFnp&fyy%EN;C69a>MvQnQFA2F|R2jRt8WZAp!bBW2~Y2V`GKg zBCGBQ?&}-2+eIqZ&}VFNC>?CQ^vTH|Vg?p7fg=k$!dL-+SvIekNOSC?vAQhC+YlwZK@E~>o^W=$?MvhYuGt#!Ezxc&Gv z-)XE_)D>)G;mbMP91~jl(O=^$4NIYsbMuS1?PY;CywtaIw$$)5hK4tf8)g=9i~Bc2 z{HjAeB39JmmbkHEzAmroQRJ2Qif&Iv+VzYmXGY}~NBG|YF8o@*nNKLnj?-23+g@H_rJ=HZ>$U~TG>d-II^Z4Nev=DP zx1pEbOnrwN+=F_>iFyvQkK1sl;~*RPC$?as%oN{my9}hBz#}i`%YB>65xEU!Od#^UnO0(|2!|jt&Rfx2Yw}^ppw~x$EJBvA?Ay}awm{^p1L$YeI+oEo)*0TuJ zDB7&94Y_>2i8^QB}-_5R~ z-PpT^lM>Mq@~8WTZ`-~hcgA3`LGL``4kXHC9md0uOOB047H$qLZB}(%SLYyyQH*`% zt3F>@_zo^)!O8KD=rQWTS59xhjv(A3{}JpYY9pVOS)EOu%>I>6W)W5^cjItZjynde zzw-NxPnqJ=|K;SCJMbgms3fJJ8o50SxjlpT zE6MGCq<1g)1SB0|7t^J$hulh=$1r#5t>SooNI2D7yI zJg`ryO^W2UBIb|WN)!byGCoV(_8GOjPsKCG`L+8he`^?6?0dci*GtTPWsBP0AfstuYTpiko6F5UI`W5w*MYyc}uUzXsSKx zxb|sZCYIU4_J+W`nb4T|D<`|p+BTQP#`nqBh^Nci;jH1bHN}v+?U&thd_#DV@4!D+ zO+`N2G|;NUrAZlQ9HMv#uR8JLx`f2<QCJJ=aAmF6<&PS{-G;qeV5U>oKHT4Q7){vu1*<)U4Z3A z@b}}NgiJ(0XWirbx_n{!bxIC27eq$v1x z#>^kx`1p0ji=esb75`|ux`MYSp977$foW!XL)Px<3ht2nY0Nb>A}$4>7A*i*cUdk3 zrj@$D-;Z$T3z#mW2q>gw)^>G;(|;6aclw%ddvi?8Cz)endnI$q!=&3eXsr)2yywGc zgi7P~J%iQHDL;#F2n<{1l+iyAcNN{7o)5L?FNWvw)dJwCChRY?1k|Ik4!n#D z^%m1xN*136-_39nkaUP$OqaeM?Y8W+V3|#0 z0+%-UEa^@gd@RB5C{@=6?_I-<-(g!QrF4p3$6YahelzClI-u9{PXrsHLFkEGVJ-J7 zr?H0H){Zeh_ML3U`{ZlG+~2jFJKs{LI?;Y_uSb1Be$2PO@x}Qdzh3kKUC(7X3Ir|U zZ`UV~R?fp#(gk_($eJQ6eqB(G&#w!}*J=HtLI3#p``E97R*f#;$?G%Vt)vUOk=~!i z+?=%Qh@zHl)Hw|-BkF=1t(^vCzsG0S0&a!Ox14LJD>Q&z*@ZvM6On)BxyU?aN_4?~ z@>rQ4Bag+|UqArk$Kz=&+?B@Ldj_lDQB55}aAn)wx7CU-fa!YnzRahs&m3B_NrL__ zCu7f|ZZh91$r#JPg>o`hj?XV+auf zOJ9%nR`yJ=Oej;-bpn*B9b$n=yU3KT+@>>atGbF|+x=WR5u44X6>0iS=})tqr9Vx7 zWPaPq%51XG4z7CJ*HEPTy$`2#3<|QMzX*SY?{i>15fItv0D$;q3_^<_~#KU;?gVEc{e7^ z3&{=R8Fv*+yTZI;otHYzN;uA{3&iYh0G>@%Su^p8x~f-OUbRUQE$+>l%Fa8kYN~v* zXm*YQ(F?I`=b=jaAL z+F@P=ek1#D*5(41-WFV3>=QbAdCT~IU0cDgFSlW2h?SmPZj0VYkup=WN9k{mk#f%g7hH=e40m zp0a?BMKSkmR81I}JcrfrFz&wzoqDbwI`2Dpz7^h#*=_2!tF)O@oZY5w8N!+5Mhrz8O5rUE9@Zqz&H$%R>rq zXAsox$oY=#r=AN#Uw3dPPfp@EvhcA`*VS0bU$_cxrfs1c+b!k~Oyp56#C*aIaN@ds zLHt@;>hsOyrCuKee?7{UdYx$>iFBy>OIQV%ozIQT214x{Ff9qd?xL0!o?uzHi95^L zt}V2v=;L%lKC6}*>^QHu?58(;ObOa{-BPl8K}UeGZ%~gIt1i0$+9nrD-F;W=-k|=jLts8>0k$;Sf5+$kd$2!&XFoEAZRa2Q z-2aWw{w-_ogxQ2z^j)9({{=hK0`}mN=1B3H_frihTw+iC{ubC&p9h34gPVeWGZyy)?wMHevIqy^CS4JDn}~F*y@E zo`{d%!^GHXZ~;IAD|h}CW~(ez7;~qdc?XzoNydZkb(o4!b3X!o3%I$m9;qO zk2-kH;xM#=7e86n(*9onzWEw*paH|P$>Og97oOLFOIqF_ZsYtW`7Qnyahpc=DJ0Ik zQ&Q5^O*#_|*adtu8bm^bI3o`jAa1MtFz`*5=T_pDXOy_*IRreo&AfXYxWqX}Iy<_6 zCmfvF+US%;qm4iFzY&c-A&f`kc&~SNWH)#92vk~~9O{!#=v3|pJ7OE&S1qK%L0CjW$O^Ilf(Rru*@o7NXbm^7b5;rEy3&{=R8^=XfJaoLg z*^{L685rnLDj%1mHudiAUt2BhAG8(v!&=I`ms0#7*3yqjRdmwfkTfdkqh&p6X`2mz z(o?dQvK22;Q%N>+f63&y-S44yOs+b%#Ey@u=l>xtyD{FucrzDz8$95{IL@5hEBF5VrG4i8HoQMu{{6Qjb$SeiaIPJh z9c>!P2h9%cD|jV|{R9D)G{HZ%c^)e4R?w+Wna|{78_O{Z?V{n9fxBRfX~jHRIX;eU z_)f%nLcUIm)1Vt4f4lG|Xw|GForY@8gO_d8YVE>dB+CJI7?^Q!ZgX<=dQ3X?uGyh}%i> zD33hmseT)CO1axGA9Wk<-_g~Vb1?+)7N6|E{M9^mcj%KFSFm1S-4S4&Blz{g6R6Tm zY$d(m>KOVXa>IV0+g~il=hqA5>!e2(=pP@yUdV%1jb7j!1$is!g-)dR1o#9b9by;L zrLTuxpo|Dm&b!0{lXlr%&N8E%AMm-$JUGeZPx#!8Nc$vTl!O-iZ2F`p_s4M`+*Bf6 z@+Dz1rmF&6is*@M#6$D|>w@TkC~*1K;eO&)G4}4>(nC-AiNEO;C6)Z<}#S=jzDFc2rZn7S;ObTr~CezY$XqQtng|C*P-G=yDarSQ1jg80WG6`(5nn`fsY9e+tJ`syg zOr+r-)5&k6Fh85|Y_d4*jlid1b~`xBjPwbZ5eKI%34Pe&eD_v|9(C|hi<4)+gO52p z2Oat$hkn?>A9U~|7N?)R0}(lfQB^-;aBubB#ao2`1g4p}!<{l$>Ku=bqWzP4*#SFo zh_42d4r_rSd^>A-76;Lka)Etj#?@G!eP7UEOb0Q6q>>U^wSW}DEAE|nj{FF_S)JT2*$GcoL z<^2LTVHI;DRxvk6mcEz^U;>t3LD6R=m@uqThPG|vD&fXZ5O?XJJ?b{g)2uoL|K`0eYoYcg*pN`6E_Jt1H#z`24Ld`8w&51^UOwFV(XkR@3S> zL#^cTKI6i)Fufr>{#KVW5)+^cFw9cm(kn}~=rrRKN9cB;M4bVNt9&kSN6Re^f$?;; zChhK?Z`wcU<39xZ89XezLMxuan0z9Ml`5XN;BZ@?b;dadceTvBTZ@jG3-=1?TN3yN z*2EKWwC|G>MiCXf)a4~RMurit^uXCF%LqLRTzcd4q}wwWXMvNy5#~9|L;ND1AR0Wv z>v#ljMwSV#=M7Th*{N#Jfc42W*_G$7pR`3&r0a0cN(*;#@JpRW3cp>`><;yM?K5k86nIjgvi4k9zq{E zzahw-8Kf=!a9^*s2Bin5HTqqaLQ zp!%;kKjzngxBK|Ve0Hm#s2H3hCP`|F6>5zt4p$2b-Q4%5ZN-FC2n=xJaPN(Gr(oX-Zy~Djy;y2?AUvrbSgoB%#E5MSLJ&M`}>Ego}u8` zV1mitZk*BGrbhZUVs}lhy9>=Eo-o}R^<#Ky^l6^ezcOQ{bvZmN{=m$C(4SAM3F0F) z@^Ri5Rq>a2U$XWo9TfhYug|#OG;@Pkw~x;FzqZTZDc>fGM1z>V1KoroCTUfFY43f7C63M= z<9+vuqA&6$XC_msXF@y1j~-3qP8AchCE2g-y0kTZfLH5s>M1K$whprt42TZvfR(uP z#7tecOxBII9eCXSYB@gEiE6^Vs{|i)n}F1tQ4oknt;6f+q_zR)rV@64=tfm=6ptIO zya%!d@)7<=Jg$H2m+^i2C;eaA|0g`IfBRt*YF5VdpW*;SAy>$zFtm6EvpxD(lAhy@*HN0jmBtJhMbBh})mR z?)n#X{Nn~7y3xP?f=Au~s&>F~H4zKq_CweOr&AObwj~1aUc;OCcf*~41NoQ^`YYjH zh4)?mI1cKDyMXw|*=N_k$KkLaO!TiAkND^Bb8yG$^-chS(zMM5Fzk+k;DteCU6p)c z{brpISp%xRfl61+UIX$9y#HSfVk`?#tM`byc9w7f_@!PKYIRSoK;hTwT);Kkt`+&A zM`9k0`Q-Y@uiN?WrZim;`6Ov^H^8%rUWb1y_gY){jJ@DM)lL?&g<6~RpMzb#T68aQ zt4M!=I28qeq(-|^LOLsL0I$HevYQwF&pcJ_!%Z{{bUp+Tmq;7NTW#!DwZFM9>^~*IQwdn93Dy7gzV)Bo_4N@h=WZ;H znV226Xntbttc;o5a3@$C7Fah3yYLW?;vpP_@?o7}JtLhD>zV%^z0;s|;t^mP`S|rA z`{;KHljWh6yskcc9F|4UC|<0t43~A(24epHkq`E04k4m{9+^8kly*rU2Xx zF7r?mAoI)PH^J0g2-w?w&7QW^F?Qa_p@6GyhWmm>Sy#vFtZKA5xk-c(Qvx={n zMQjF%jB+k|X#-YPZ^FG*k*(OZ#hn#P!`Lkmf=q_Nhrx%sePrS9M=}3<7v`An8bE6t zRMDM~KZTP*5$@K)ZVc}9!d)8q?vc~Mrjc_?p?Vak>qfeEkIXX+oCM0@p6guq+p_y> zHZV-R!1?D7!p@8*3RT0aDgL>VCsCy$;A7op*0ZiquDYyUYTPpHE=WD5oa#2pI+o)T zxo21e@^xy={Lw!?emQ*;v})!`xMS-aco`S!7N#SF$1kV6`}T973rIS|E~ZPbET@u7 z=IxboSy$9^V7zXWfMC+zZ|y8I_A2hMb{cd);IoUAdYiHwLDu6*k3l*UGUFhNO2Qzf zY|}D#(#u?L7~#tNZUng8uS5BC@7JLMc{rZVaLTsQZi_ubd+kzI<@wq(2!|m0fNi!O zkH5!tm=zxsw5Px>@7%GOgJhj?+ch0=`zQ6O19sw4V@$dVoWi#QBv-D=@lpP)f2<}t zpIG+=1m6vU^-uE+!!B;*6`bo3^p9mtAYZ4(%pcwO_~rCL&~7&@`ky=mnr6PWwjY&1_sqOUIz}UX(%!8frZo>bK*3H<#FJh*J z!7R$mrjx03GJ7&M9nY8+%?6%n>(xX>){~D_u zTd|58GG7+jwpE3Lb_Jras`2GEelL_O3#|=UUC`%FH*z)N0uziC+zVl~5UR%jNmd)m ztwP9`%-C{r<$|qpE5dF?9D+?({tfbv+Y+Y1QYQFY(M5>!5zs5OqUZUt15$hat!Ozu ze=AD9PM?4D(=VN`gH}x|x(ETugO`%IS}V%lcoaMWk`A$p>C!7pr|3lUcBxj>9!=K_ zltj*Y5LiZRHSv)?59t0;&t|kt#AkQ&L`$|KjP4SH7EdkOvUFOw)y`c{XoLTjRf2^kJm$j}zWm#fzAYJoy zJY#R-tMydStd?RoOEbQVp?IU7xYxhUdsB+f{J+=zS$e>}qRX*9H+*qMP#|a#zkcE^ z`8?}ZNk8#ir3+&9>!)&je*HwgPRB#~$H%Xqj)3UOB6$cj-8MUjbesXLl78Z-hCL_& z@lWhxy7cwXPmR`NmI?I{(;E!3H@mzH9#~u8%gFoTmXDrS*Jn7(P zElxk5a`2~t%g&f*fs6iM1}^&lb<&NR(s%I4=!&|XUzn~|x36VZ#orI~?!aRI4$r!M z8=eWcg1#KU=v>b1Xc%Qg-QbSq#$Xo+TEwqsWj3V&?tGtojd;4O9coEK&YEJ7m#_;D z->t+adY11Ha(Luy2kqkD9Tty}2>3dlPK}vA^6~NO;}=15(<}bbgvfjFGx_BJEu`!n zCRTnGUROB%M{zFF*~~PNd)5n)`vKBzzi*gyi)($5irX9UoG*#sgd4_y*xl>>4{>jB z-{5XLD_eP1>R#+#YYOsSIhF6L|KUEiOF9hCud6TLFUB5W zyc`Ue-NG_{T@jzZEgzpNxo`It6KH{ThTzvZTy=W`^h$lZT_VKVmx7M)>zs0YqH{!- zkgwDFMT6e+@#~U>-N9g*F?5EET8n3OuP!5!pE^7i?PG?bkEYuXIsrlyG|^kg6)m&= zS?y=QCw_pX2&cUiRJChnQ}1BJzb0#DhRT%s;GPdptVwQ5iBwxlSR?pO#CpJ5(rIxT zbmQZ%O@~1n#3LZ#(sXOnG6+XNV~Z{|ibC(NOjTvhI?&f4gU&e45Up4i~Mn>?|>lN&s>;hosHIgAr&Vcxxo zcY<8o;HeGB9vjx`4GPBgFdYOGVU3B@&b08ya=u3 zyE2YcT)#dp5 z>^mZb^s?O-kaUP$OqX6+3gM{(rPe}hw?T7JJ8ZN3 zEF<<$*^d#Rd$(9%(k?p=NT%KN548|GOCM7t6s>$v_}zgm{gplyWmNi6%oAA)8FTO) zaOq!BAf-=rnsnROdV+Lk96TLQ&N%a8tKSdRSN+|??;;$6=obAYUW|jej=(Xnan6T`ac_O+t03zU;{j>D$F#8!##ldlm^m$gd`&cg13$iXfUT{$nu zCvqDgTFL9S znNQOKBC9Xs!*CfPf9w4;GAIVR0R1TiE`2@ph8sqy`(q`~qF^jF&b`s`fa&V>*|Fc% zOLr4$)qdES2YhJ%G)#inKWD7^Ul$w|j23t^P9>@p5I0Tet6a&DIhiR~lFp%3I>yt- z%)3C$XMYnj56>#?ldco8{>t#=G#BfX+%?(;T<#R@B##}_bpw}sQ(1rIe$fbVJ6^k$ z{C2$7J1AcTH$$vSW3i!u>UTy_UlIoNf8oB+^|%|xKW@W$;^}E@E7L($`B!QTM|lun z`4c+uu#StqVE(xv_21t+FUQAn;X5o70{K{m0(9f!m+vE>Rnt4afR}UNt<*a|3_U>I zCBQICflIF}->#-9-8+{Zz|3FDZwE}`V%M@Xt?yOVMngWgYEBL zYHh8_6L0IeP#9)!#x39z_d& z5MN$7%+g@Xjs5&Dw1T%4ytw<}g;wwe>+Nm-xSs+$mUz2;8zqa{k^2t=D)8tHjn@~= z4m<(3n&_6c!@pNQU-#wUuhxF0W+5=UMK#>e5NxPxsBhTN&@f3Jy;FSk^OiQhiw|3l z1P%Z`J%+z~`FGDfv>&*ae+C`9hZcPtlk7kSn{G*~nc%c(?HVk~9e5^}d)-Kv_8Fm*$J5Z}pdsgD(DxkbWf9PM7hy{rsH52iu zrJq3j*y=HUEI5fDTW{AtjB7IgNc#J>b^c?YQaOIVtTSP-`punVr8P$|QfhlaFF8Q^ZX&pP?S^hmh= z)*}r6zCw>INLV!C-9a3-0zle!Rj|$Ow|< zCL_q>bYmd_SO*$ya#^n%?PzkCxQ#Tj*gMO{*W@f4<0U-WAMjJgHNVzsCauE5E+_9+ zsd|JuSpDo5dl7^I{cl%l|CX~~`feu7a78gPjqYrzkK+Ck%!CCo6IP3vu}x?LH>#Ig z8uH(7*^v7_+C$uj#Ba~;h|nv1od#{{PSswAop6{56I$1uxVr=@0JO7)hWnjHHIKgE z$yZI(A+VKk}ye~h4(e^*qGjyQgUX^fbP43K=fC{zW zp#E31&wqrSVSmu`H{bk7{i~d1yNa`Wub{18L_2TqPPs{kzokXb{N?Dc#Gn3_zCUFg zvv^UnLl9Me^qnsT^^6|Q^zo}W^?$WbExr52VEtcW#~|{%75Rx3ylH$HxSyd82=%`9IY5n!9fxKO^C4$8lOw7v|7Ujbc!VU_}y zUb#0fsW(2A($7|%X$Hm%vZ8@y#NPdN)=q=&JA8JdHw=;PxBJ}h@!8ov3y^<8EHG(j z`zS#BFNp;v?Rs>fm7z0<=v_R8sjPyFqLzdeEeVjI%38DpwOjH#~5zc9Md-o3Xu`u(N0Trk+44=!z2b2K|OS==rY& z1JSRw*Q#gGt|N!w)`5K8kgHp&&8v~q^B=)E%@+6zJk_*c0q@a^!$si zS`}tHqvL>Z(3UOKe`^hTf6JAx_os9YGlj@wW315oAvi?fR!Q%lar~lJV%-Itx>ht_ zIX=JMCtoK$vOxd%`1L;ZVl{gII3ke4`;5zKdjB=>-3%T9hFJ<+`g-Vnt2z|RgnGWX zAB`9|O2Rv3hQ(MzpVJ>iXFRF5WJmH@2M@wuq3?2V?X7uTcV{cj^{ngn)N7(mIv?Mc z)snSOVTO@kjE`*&bRWDKc7bv-@+|rutgDq|WWRW1O`Ue&eiaufOJ5Hev6Jk2tVbE)oQnXP(j8)fNxLf>cGJSFl@#}T z>ZIv6W!D(XS$2xiAGs5=cW}2%*X!y1O0x3do*SL5`cLWt%ZT+$+5@-0N=D&h{URPA z5kS6b>iS{uVaVx$_(v1f)`Mjbj=)BlU9GPFRQKH2+InCSL(U3$LxYw{XMsGeEyyr`KoEn4uY?mo*U0n z44h>XTuZ0-pZR0&lbj=abA75jBB3S>#=gPHr<3WiLmkf2H&ab(qX9wE>se zCHB7M%>E(L?Tpf4;4(E z4F(Kw_0~LU&6Z|$ZSY52MaOJ4_RhjR*iyq4_2@;^BixL4Q<(2@&n)!{d0H?7BQ(6n z@4{nM9W&nAk1K!X<3UE=0@A3#uN%UUl?Yra>4ru7z8E4qe%(-x&#xQE=gI^9Eb^N`Xm7(G?&T^T^|3svk%c4Rt7g>4yg zsBWFd>mIoD%CZ1Y9Vm6XBkL%EvdX$|YxHz{7GLEWKc0}YeCb4igzrBO?p;$&#nWSe%B2FmI zJRF}&PF&6<1S*XDWOmz*xz-NbVHYUZQoVteiajpY8op0H+PkbB&KeF{Qw&?QE9M`| z@kvW1?~_k78EN9*n8hO`0$#&YjTAS+g9r2*=1=^i>B(8i&p=43n^D>;pWUgVw<#kbS8vFOSnt2UZF51ZNBA9^ z;I=$ZV1$-%vjEoQ^a+3J6M4sVC*4ZjNEqXMra*K|a(Z?u!L7@Qi7-{eBe+#39G`k5 zelioDg!=hOC;}6swX1+Iik@}Rm4CNxNKNziRL`MGQr0TTe-1n@NWI?$BHxvoopYIh z3!h*9$tQK0uL$3r7H6CYe~hOZ`Tsun?&Av<#6Oy@{C@+MbD&j{|0yKs4)F}8_~(!` z>eAOk{$=*dgtJoqWk!x=OZn&MRv-k#f0KaK2U<|e+(TleK#57wc89&%d)Y(BdL(=3 zD4%i)YnXJqM}i(?j;7^+XW@?5GQHouvL&Gk-SCEvO`-S8Q&=OB&A99No4AL0zMFSF zLq{w_Kj74RF2uW;xj!8DGcRKV+7!gz@19zP+eZT3)ECqT7==DZJ8|v(`?98}dja<5 z*!5XotVX`sjB90cDm8dddxUP@DS$lbZX4}(T$IPWP27g>JR}*2TfNG@GQYO&{$jxaR`RDgf z>|#ndv|o-MV44X`KfaEnartAvzy)ku@%DC&!GU_fKPx7Bg74`9@q}_*9Z#T(%?mFm zq_&mUw5jBDGV2mDSsY8$?{BR)F$lvDUBL1X`Yzz27orXwsJEY1M;qiqm*E_$D?^kDUK<8~l7cxESIo&m45iB6+}%+4Ie3h`*^%lH)t4iwAeo zj$0y6^F8>p&=SZk7UGc)!3{Ld%H!5s%mj*??(3BJR-fCS`5@1-b6<%7>pj8WKgq!% z4|=7Uv|-0D`Xg4>OSgYgj!*h0qHoB@`Yk~J`1tkBgCJHjlcqaJ;ALDWN=z^1l6ns+ zrT}noZ}(xCrNE_Mj=pjIq<(Sx9gJ6-!$5n7&o26fWk~(Q_FsVfqhf(c`~5z9+-INh z*-!ZFx*wA<%7guwxryY%oVN4km7`AbBi4I}+*ZKCYVXyH}55jyY?7kM-BrHcXK+W{-HzY-sH z3*V^}u3u*`Tvt9MT$*kl&I$_2!{rnQW|LWbmp@rqn`x z_Y2piu(o7c^UX@HO`+u{D_Uxv{6MSQ!Njoj&hey%!RxSQ{=r(8I>?AyKv`(;x27Q! zYA0MOwWjm-eKDluS>s*FD97h-P07b_1?V3izhs;Rt(w+!43+f^co~<~TGQ97lnhB9 zyhA_nk41kIIQSgN&j=1$`{T;K0j2`*(qwKBoz9!z$6vSFG zd*>X{t0>)qUDrkDYlAuLS;^01r@bESw`1Q-9lGS8Ew|R>azk5lZRBac3huSwty5p( zOd(DOK;Adzm`~ip0vU(Qe+z!(ml0;J2fgsRU=Hin9jEL60z38*ek;Oo97*S&pxvkUdunPn&;@1(U;cx_Q92xU{^07X5S-aH!uq!my4aSNU zfpUEQ83Xd!Dok&5xHPFt7>6hx!dtMg?lXSUDl&eYG2r`%pB5qBV_nL>JHW%JNAM8H z*J)7wPd7e(-82T`n2(QE^15y32}EESGz{c)_>4Ov(Fx!eipdsOr}lV z1?qkAl4+2yUm9IHozS1H!fJh`*^9mM5$-DbE<9C85M63!FY>VGkdL@C89EU<3bO~f zQ2RBit!Rdz%xZ{#byePx*#o-U*-z+a=;#_1Zo$bVJq!B2=(P2j^?cN1mHub>5d1of zCw7j2Ua6mRjxRePvbGB}t4p+NIX>zpz9TX~zE1sy`J)>jzb<(mv}*b}C!kp9C*!hO zKc^e%{RDUfBpqTG)1|M6F0qFh70ZOW;Tj1DW(d!XK6{VPKJ2qwjX)tAR~(J67___N zc}nDpg^Hqmc(P}Q`6s6`sNZD&4*Oj)n;9mZN*ZtwkF0DQ0xqNd-l2igUz{y7iXM{g zR24elGy?{>IzX4#6)cM)e~h=_ep!49b(ncxNfzC@K>wt!`em^kpI;WqSB)&Pt*Ay8 z*~sU>TS*pk;A5NxBpqTG)1|M6ETT`Xf#pD1++poBD2rOQWKTeBGMz}+2Dyl)=s<37 zY|%R;H#C_oYTmxmGIf4WWWX@~4A*(y>-V!(=jF~t)*ZKQ(=OoB*Q3s3yr@Cyyv$0I zxU$Zhi_84A-cWJj-_%rU+<52JeYP;T+06UWPQ^aomAK2rB;X3#-RIyGkg=*Gw2Z@dUvsWBsYp>jM} z%PyDOytjUGa%&eWY{(qN7l6CmK5DHjTef9v+XX1sKPMKLj+|>jEwjtTRyu2x?mBvX zLDnPb3$i~ZeL?v(@c@8(PCIm(vJ`@c*~I;FCXt?V?|o$GWuO7b2fBAGL(^BD(C^7TKGNT1!T+z_>l~WQ$a}qKS!L~%^CvF8Ua}rwC@Ck6cvAW{!$-Xt5KVGmI zR!-KsF6aF54HeEGx0>_E=IpUve>oGx?kHxT_brY356>PmKUgkr60s1pre7aad-j-X z8!m{|uMf)c`SrnC)=H|;2X8>m^N1kz0d*VGOS$r|m9YPQC+Gr_4zY{r(l19J$b4oP z9+oxnui1&X2CxjkNY<3f(TS?z!Vq z)@cEe;|>tWhw7|>dfx@Q5jc0p_bc&Hj`>am4}t!5YRvr6jgP;*J_6bx9svoLCPdPM z3n0wGM%iTA%E>3sJhH9}h<{=i)1_CIPd6sa3&{=R8+RnhO=rw2$`{2Vk&ee^a5k_% zb_^#2WB3w;nekakHy?!*6p zpPGZ2`*ZenVd_%~ptp6^=Go^B1@Rr!p&wn+YJw@Qzr>Z*V!(~QcsJUBJ44*+<}oqH z+&n)DdyPJwTK-0Pogc+_$^Y8`E|agp1~BYQ*D0#~!x~;MU;8V8yAO;V7{h(?wVij@ zHr;)%W*XO_FcO6wzH*bi^?lv$kbj`wy+NLJ-()#!ssZWKxw6Jv`Nh4YxytUv(x*8! zRc~HYJsO`#9GyF+SF19~Y1FjIRFT8wUOw-7o{rBP!wT6NAPipC2UkzI`69XI?{A!e z0$_W<^*z2%KIUtewTom@SGXW`&)?rD$0vJ2Bz`$~7Ir)ooc$8UA&Q64hT7i-lksCS zCGoo*xWoadI)ld(DBzM_?j3Rci#YyCzl7=ic|5Lv=U|`2BOq>{1;O=izvCbKHWI%n z;PMXr*apinA{NArG}pf)@UIgzrkC3s#6OmiyaQDI5-jc=3F7t}KE6dbbn^uZ@Lt2O z;@=H--U*j;3=;0|0T;jdB6qHaiC7T-eg}5fzq4?NfW~yNT*NYj78kuxJ{2 zH!jO4{39SX!^-lafArVipTssbH3PbU_$T&K=H=`Ibp7F88-_FN5sO1zd4s<6M$HSg zIu+i_XbqXN0@Pv;KhrHhS7{$fqy0uA7HIDg3ryN2Zp^!@AxTk~1nLO3ub+ZRH$n*R z_ZZaL(fs=C37=heTjP^xqqSz#A6fFg*`$$J3|}Vmz8Fm0ei1l01UN6mA`IXOIz_gTm6$X<^1WS#%aiJzG%Zd)xOOIAAQ-iD7+Oy^TH(?Bc7Fon zDPJj|t}OZ*0Rsdu&J2s7!?kqn4{(~=AIrn^lAmSGISBb`7W+n~Pqce*aBu1ROZxl! zuo_IL+$ZA6I|B2IT1UR4C$~b3svJ&o@)T#`BzN$~W`8K&2_owAF!7zv%{ky5I63t) zeIku^7bg!+SG|mN!i&Kg^WAs4R|TP8u8OU|lq;ZD1cvxDGYvVdcVGjcfNgneYZZTI z;D`QB;ccdG{lLN4{iCrv;^~RlZMd%@H50pwqBj{IPv{RAYTm@`_!na1shMm#H8llk zkHq2+PsOGa)A$D5`}@s9)A_<3AgV`y>`b<+!zM;-(@b{S((Z(#o zg(Ax=Cm&^wa|E z>B)D53>N4gc|U1Q>LtPe}{B1Pvin`awM=N>Z^fLx@0Cy3qH%zvqGAl_yf!Z6uJ zx_LmqlX&PhhKKGC!xW(VuZRUE?WgfD?2CAs5TCEY6rlUJ#R8M|SA6y#`t0me3Xp%u zXaB6vp7Pm$%V#fc9LAOV`O>OX1REFk`;6rV=58aT11$>H2XEj`$p7N(qBQFt#QUBN}LrGz_1!^|A}EW+CdD%YP5YghSk`N zKfo(^8f`y}d#UL^dAAea1_Tf$ZZ{0|?vehA?zG69&%o|7d)oSUN2kwdi{o95IQP=c zSo13x`ZPMq0Ow^MJN5VK!#t-mh+B4O2J7?cV-~*!b63w^`evvRXJ^{q+1J(>#2)oG z_Hho2>3WWFYb|k>j{cbQJGgygVKX!%%N>0`%;{DYHwuGF zM&9SMlaJ*=pLq`FA(+fdu|EQw!Yy{r0d+d|-vu6a?Eefn`$EG14d5J8iv7=lQ~iql zRp5*R+YiR~$1oqqle2c}W%3HYtT~GP<8W`r!!Y^&XMjiWoU!(C;H;m*|Ld?bAH@Ez zVBh7~)oqo>E4VR0wu8>bG84Ec5u+NOwe-FaPdUc=tUZ(SP>TaQ__+19vc=NQkQ$3r)9e-yZY79~5hTrnz}wCzdBAz7s%n~X9`zU+Q_HD9EWe-R1p5Zmg?BE*CGA!E68PH}o${n4kD|BCmjjA@JUUk4mT;#^2qrfSA zJ3w;fs~jKYkncpS7v!r(z7B(L(7r=M!lmiT*D?r4K%<^mO}_XAqA+*_#6Pi%>C!99 zmm3r2ndF-BP2Xx;u9C8+gdSJ#u(v_Ds`g`WuN=FqyuR>ZT{Pt&WqKvm#SW=(FeQEt zNuw_P{jH0s@$3{T0jz5kpi*yUPrtBNu8ptToBu|nUGNZ5BI6AnrPF=`A;@+R;251_eJ?l()M@0*wm<&_hOc2 zc@_^Q#myP)`H z!COh|J^?=W9$rZYUM&Kbz8*C_Y<*{5vsWV%;46A5>}V7=#g%lXR1EhOWWw7QSGJEo zv{%?GOU06n=}M`ni%>FxfqX~LhTKj_#qjHwF12;NyRU77%6DV_F+7Sn)cUvfUD10# zO}b1X%hmSdHV?#*+TgG4<@o%yoqW~Q_Q$|iO>O7=TQ#*k3qE&eqNGF8C8kSXkJ{d0 zJ!W37THAHUc$MmII?kJV_x6?OAFs0KVR*3WJr7}a(g0H5Ii~IU2+mFXywr=e`~83P!ijzxhr5t+x5MO-q5X^os8;;rnkqYt`M=pdzh}xD!U@wAodU z{is*zd%M_bY1tEhqy^#_U8iYbWB0b}Rd;J&KGbtGeuA-6WSkU4)z(g=&yO`%!5nDi$i18c;-ViYLA5iA9R! zgC8okP_aUheh{g2g@c|DMExKYTB}mEA1Vf^3Kglp-|Wt1-CoT34;+}AH?#Bi?abRZ zZ{EFe@>!8Hx*XKoXxiR;MOvk@FQk7BcEjox$9pI;c8PH`$B(}7oL~g_VB5TZ&h#a! z>!HsPexm(9oNu&oW4WCX=T>hP!24Qv^_T!1TJID__}`X|Fmky$o(S@A@3~@aYepJ)mZBo^#f#zInuJypFQZ zSM_;}t7aw6TrdwTea?e(po;K;AKZvQ{9r4Fo6&2@FF-T#?pQzZg|nv%c9*zdr~UJG zN}acHi#zP3orle{bFi5Pn`f|h2HeR^VDC)+9OAMIHrY@ni!#|3H@|b|$}E{U7v0d5K@teYg(494nJUo6_27@paH z_KUnt-po&)0iqw6TPw%2i`;@!*eV>`RSrVS9s+HkZ9HQK&)CJonO#0Fa$^bABbVV` z#|d?)e)aUh(YsXcy@Oawc>lB;71*{@`c6rW)W7&6Raqt>UzFl@nS?M%iaTTy^24zX z)l=zIy4}KZbx5ElbC`WdP`uUcJVtJK2wBK;j5S*d`gu3ve0E#-d^+|V>TlXMpeg?n;t!#d zQ}C?s?O6Vkh@ZgsjWT~e{|NCpbaM(JQ!!@2RClXv5Oub#B7-xp={>=jSG-pN3)iXvEmLh82@l0m z@#0O5phtE;_{5_;``e*y53<7R^o+{Dqmi$sflnh}UM3E|yXd({YB zi@*mX@SzAi8-ZU7;o}Gohww>+Y1C`Tz(fE@SjDmv9fzW`mQZh_mBQcm;bR!UY)?b z$mI=nd~5R3FJ{0uz2m2H&w>9;g3eT!zKrP#>75pNHGY@yy@J_2W$i`U&<6oe{C}0c z%xJs>Kj^-8efTBXFeSA+7KSDWQF`5f5f{tHZwSk{VFk?BAHodyj6VKtm_u4S`_W0R z3FPHBE(yBgCHn79d}=}UhbP-(=ql6i+qToBi!%_5xe(*o1}&Mo|1 znEVi|VE((~ZmHxhqH{JlY-Hq1%Tt~SyJzM<_m}l+&+5Gz_FmMh>L{fA;*{|F3XmFl zv-b^pC+gi#f1Gxh&&X3`c-Q!h+tI1*E=TyyY$x|?>%h0I2M@m%pSch8?Hrlj#b4%O?b28w&(a!{UUHliIQ=l(*Na1gmW!2%mnnwF&q^J7Ow&TsG z*92{M<@8>(n#s*g_&KzVe(Z;?+ZlvssDF1OaAoCxIIShF1|Ps{Tlm174DhjP0UsP2 zr;hhoQhBd9z(ZY+8+#$NtNmfnBMbQHNzVUu9Q;$7^I!6=mm-S{xX~`oyVmhwC!Q?D zyY~KZ32Iux3Q2cBrkiwZv3zmfmHGNvLFm|3`Z#?mBVRkb>qRVp6DZHVa4Z~eEBeIm ztcz#HMNnjtbQn!vnm!pS9#lczm3^QiO=xAyfNCIo#y*o?;Z#Cggx?v)Z$`*5@TXh+ zc&!L<5}i7NFraTBXwzcv!;kESMiI%|w%w0E$#4q}`512JrK$w(eh`M7pJG+u2k1`0 z8~74nV}tbyU}JZSJh4e9KWox!fK6FH0`D4{)~Z|jDp*ij($~?_=F;$3>;Ehb4jSXE zOViiOXorsYqBarfYgA?z$Ts?%$qv$-E;kF=8gqtwTuuYZgGdt`$f4%Y59*#2W=o9bc4e(%OJDBDbw6Uxmh>LxUwfKBin07X4+ic~c>3@fwMeC%#EXQRW7uXsTLCCnl#SCE5D@qj!kB4#Y z-H*c)-+W$1coyF5-R}Y1gHAgL`FtBf${bj)rhk7VI5a!>Sa6m6!j^Z-(4A0p1T`c8 kEl~VTg^=Eq5(xIK+qP~Ak_ZGzXv2Y*L_8e(X!e}H1LAUCy8r+H literal 0 HcmV?d00001 diff --git a/software/sys_controller_bsp/linker.h b/software/sys_controller_bsp/linker.h new file mode 100644 index 0000000..6c690c2 --- /dev/null +++ b/software/sys_controller_bsp/linker.h @@ -0,0 +1,103 @@ +/* + * linker.h - Linker script mapping information + * + * Machine generated for CPU 'nios2_qsys_0' in SOPC Builder design 'sys' + * SOPC Builder design path: ../../sys.sopcinfo + * + * Generated: Sun May 03 12:35:19 EEST 2015 + */ + +/* + * DO NOT MODIFY THIS FILE + * + * Changing this file will have subtle consequences + * which will almost certainly lead to a nonfunctioning + * system. If you do modify this file, be aware that your + * changes will be overwritten and lost when this file + * is generated again. + * + * DO NOT MODIFY THIS FILE + */ + +/* + * License Agreement + * + * Copyright (c) 2008 + * Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This agreement shall be governed in all respects by the laws of the State + * of California and by the laws of the United States of America. + */ + +#ifndef __LINKER_H_ +#define __LINKER_H_ + + +/* + * BSP controls alt_load() behavior in crt0. + * + */ + +#define ALT_LOAD_EXPLICITLY_CONTROLLED + + +/* + * Base address and span (size in bytes) of each linker region + * + */ + +#define EPCQ_CONTROLLER_0_AVL_MEM_REGION_BASE 0x0 +#define EPCQ_CONTROLLER_0_AVL_MEM_REGION_SPAN 8388608 +#define ONCHIP_MEMORY2_0_REGION_BASE 0x810020 +#define ONCHIP_MEMORY2_0_REGION_SPAN 36832 +#define RESET_REGION_BASE 0x810000 +#define RESET_REGION_SPAN 32 + + +/* + * Devices associated with code sections + * + */ + +#define ALT_EXCEPTIONS_DEVICE ONCHIP_MEMORY2_0 +#define ALT_RESET_DEVICE ONCHIP_MEMORY2_0 +#define ALT_RODATA_DEVICE ONCHIP_MEMORY2_0 +#define ALT_RWDATA_DEVICE ONCHIP_MEMORY2_0 +#define ALT_TEXT_DEVICE ONCHIP_MEMORY2_0 + + +/* + * Initialization code at the reset address is allowed (e.g. no external bootloader). + * + */ + +#define ALT_ALLOW_CODE_AT_RESET + + +/* + * The alt_load() facility is called from crt0 to copy sections into RAM. + * + */ + +#define ALT_LOAD_COPY_RWDATA + +#endif /* __LINKER_H_ */ diff --git a/software/sys_controller_bsp/linker.x b/software/sys_controller_bsp/linker.x new file mode 100644 index 0000000..133a801 --- /dev/null +++ b/software/sys_controller_bsp/linker.x @@ -0,0 +1,405 @@ +/* + * linker.x - Linker script + * + * Machine generated for CPU 'nios2_qsys_0' in SOPC Builder design 'sys' + * SOPC Builder design path: ../../sys.sopcinfo + * + * Generated: Sun May 03 12:35:19 EEST 2015 + */ + +/* + * DO NOT MODIFY THIS FILE + * + * Changing this file will have subtle consequences + * which will almost certainly lead to a nonfunctioning + * system. If you do modify this file, be aware that your + * changes will be overwritten and lost when this file + * is generated again. + * + * DO NOT MODIFY THIS FILE + */ + +/* + * License Agreement + * + * Copyright (c) 2008 + * Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This agreement shall be governed in all respects by the laws of the State + * of California and by the laws of the United States of America. + */ + +MEMORY +{ + epcq_controller_0_avl_mem : ORIGIN = 0x0, LENGTH = 8388608 + reset : ORIGIN = 0x810000, LENGTH = 32 + onchip_memory2_0 : ORIGIN = 0x810020, LENGTH = 36832 +} + +/* Define symbols for each memory base-address */ +__alt_mem_epcq_controller_0_avl_mem = 0x0; +__alt_mem_onchip_memory2_0 = 0x810000; + +OUTPUT_FORMAT( "elf32-littlenios2", + "elf32-littlenios2", + "elf32-littlenios2" ) +OUTPUT_ARCH( nios2 ) +ENTRY( _start ) + +/* + * The alt_load() facility is enabled. This typically happens when there isn't + * an external bootloader (e.g. flash bootloader). + * The LMA (aka physical address) of each loaded section is + * set to the .text memory device. + * The HAL alt_load() routine called from crt0 copies sections from + * the .text memory to RAM as needed. + */ + +SECTIONS +{ + + /* + * Output sections associated with reset and exceptions (they have to be first) + */ + + .entry : + { + KEEP (*(.entry)) + } > reset + + .exceptions : + { + PROVIDE (__ram_exceptions_start = ABSOLUTE(.)); + . = ALIGN(0x20); + KEEP (*(.irq)); + KEEP (*(.exceptions.entry.label)); + KEEP (*(.exceptions.entry.user)); + KEEP (*(.exceptions.entry.ecc_fatal)); + KEEP (*(.exceptions.entry)); + KEEP (*(.exceptions.irqtest.user)); + KEEP (*(.exceptions.irqtest)); + KEEP (*(.exceptions.irqhandler.user)); + KEEP (*(.exceptions.irqhandler)); + KEEP (*(.exceptions.irqreturn.user)); + KEEP (*(.exceptions.irqreturn)); + KEEP (*(.exceptions.notirq.label)); + KEEP (*(.exceptions.notirq.user)); + KEEP (*(.exceptions.notirq)); + KEEP (*(.exceptions.soft.user)); + KEEP (*(.exceptions.soft)); + KEEP (*(.exceptions.unknown.user)); + KEEP (*(.exceptions.unknown)); + KEEP (*(.exceptions.exit.label)); + KEEP (*(.exceptions.exit.user)); + KEEP (*(.exceptions.exit)); + KEEP (*(.exceptions)); + PROVIDE (__ram_exceptions_end = ABSOLUTE(.)); + } > onchip_memory2_0 + + PROVIDE (__flash_exceptions_start = LOADADDR(.exceptions)); + + .text : + { + /* + * All code sections are merged into the text output section, along with + * the read only data sections. + * + */ + + PROVIDE (stext = ABSOLUTE(.)); + + *(.interp) + *(.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) + *(.rel.dyn) + + KEEP (*(.init)) + *(.plt) + *(.text .stub .text.* .gnu.linkonce.t.*) + + /* .gnu.warning sections are handled specially by elf32.em. */ + + *(.gnu.warning.*) + KEEP (*(.fini)) + PROVIDE (__etext = ABSOLUTE(.)); + PROVIDE (_etext = ABSOLUTE(.)); + PROVIDE (etext = ABSOLUTE(.)); + + *(.eh_frame_hdr) + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(4); + PROVIDE (__preinit_array_start = ABSOLUTE(.)); + *(.preinit_array) + PROVIDE (__preinit_array_end = ABSOLUTE(.)); + PROVIDE (__init_array_start = ABSOLUTE(.)); + *(.init_array) + PROVIDE (__init_array_end = ABSOLUTE(.)); + PROVIDE (__fini_array_start = ABSOLUTE(.)); + *(.fini_array) + PROVIDE (__fini_array_end = ABSOLUTE(.)); + SORT(CONSTRUCTORS) + KEEP (*(.eh_frame)) + *(.gcc_except_table .gcc_except_table.*) + *(.dynamic) + PROVIDE (__CTOR_LIST__ = ABSOLUTE(.)); + KEEP (*(.ctors)) + KEEP (*(SORT(.ctors.*))) + PROVIDE (__CTOR_END__ = ABSOLUTE(.)); + PROVIDE (__DTOR_LIST__ = ABSOLUTE(.)); + KEEP (*(.dtors)) + KEEP (*(SORT(.dtors.*))) + PROVIDE (__DTOR_END__ = ABSOLUTE(.)); + KEEP (*(.jcr)) + . = ALIGN(4); + } > onchip_memory2_0 = 0x3a880100 /* NOP instruction (always in big-endian byte ordering) */ + + .rodata : + { + PROVIDE (__ram_rodata_start = ABSOLUTE(.)); + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + . = ALIGN(4); + PROVIDE (__ram_rodata_end = ABSOLUTE(.)); + } > onchip_memory2_0 + + PROVIDE (__flash_rodata_start = LOADADDR(.rodata)); + + /* + * + * This section's LMA is set to the .text region. + * crt0 will copy to this section's specified mapped region virtual memory address (VMA) + * + * .rwdata region equals the .text region, and is set to be loaded into .text region. + * This requires two copies of .rwdata in the .text region. One read writable at VMA. + * and one read-only at LMA. crt0 will copy from LMA to VMA on reset + * + */ + + .rwdata LOADADDR (.rodata) + SIZEOF (.rodata) : AT ( LOADADDR (.rodata) + SIZEOF (.rodata)+ SIZEOF (.rwdata) ) + { + PROVIDE (__ram_rwdata_start = ABSOLUTE(.)); + . = ALIGN(4); + *(.got.plt) *(.got) + *(.data1) + *(.data .data.* .gnu.linkonce.d.*) + + _gp = ABSOLUTE(. + 0x8000); + PROVIDE(gp = _gp); + + *(.rwdata .rwdata.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + + . = ALIGN(4); + _edata = ABSOLUTE(.); + PROVIDE (edata = ABSOLUTE(.)); + PROVIDE (__ram_rwdata_end = ABSOLUTE(.)); + } > onchip_memory2_0 + + PROVIDE (__flash_rwdata_start = LOADADDR(.rwdata)); + + /* + * + * This section's LMA is set to the .text region. + * crt0 will copy to this section's specified mapped region virtual memory address (VMA) + * + */ + + .bss LOADADDR (.rwdata) + SIZEOF (.rwdata) : AT ( LOADADDR (.rwdata) + SIZEOF (.rwdata) ) + { + __bss_start = ABSOLUTE(.); + PROVIDE (__sbss_start = ABSOLUTE(.)); + PROVIDE (___sbss_start = ABSOLUTE(.)); + + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.scommon) + + PROVIDE (__sbss_end = ABSOLUTE(.)); + PROVIDE (___sbss_end = ABSOLUTE(.)); + + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + + . = ALIGN(4); + __bss_end = ABSOLUTE(.); + } > onchip_memory2_0 + + /* + * + * One output section mapped to the associated memory device for each of + * the available memory devices. These are not used by default, but can + * be used by user applications by using the .section directive. + * + * The output section used for the heap is treated in a special way, + * i.e. the symbols "end" and "_end" are added to point to the heap start. + * + * Because alt_load() is enabled, these sections have + * their LMA set to be loaded into the .text memory region. + * However, the alt_load() code will NOT automatically copy + * these sections into their mapped memory region. + * + */ + + /* + * + * This section's LMA is set to the .text region. + * crt0 will copy to this section's specified mapped region virtual memory address (VMA) + * + */ + + .epcq_controller_0_avl_mem : AT ( LOADADDR (.bss) + SIZEOF (.bss) ) + { + PROVIDE (_alt_partition_epcq_controller_0_avl_mem_start = ABSOLUTE(.)); + *(.epcq_controller_0_avl_mem .epcq_controller_0_avl_mem. epcq_controller_0_avl_mem.*) + . = ALIGN(4); + PROVIDE (_alt_partition_epcq_controller_0_avl_mem_end = ABSOLUTE(.)); + } > epcq_controller_0_avl_mem + + PROVIDE (_alt_partition_epcq_controller_0_avl_mem_load_addr = LOADADDR(.epcq_controller_0_avl_mem)); + + /* + * + * This section's LMA is set to the .text region. + * crt0 will copy to this section's specified mapped region virtual memory address (VMA) + * + */ + + .onchip_memory2_0 LOADADDR (.epcq_controller_0_avl_mem) + SIZEOF (.epcq_controller_0_avl_mem) : AT ( LOADADDR (.epcq_controller_0_avl_mem) + SIZEOF (.epcq_controller_0_avl_mem) ) + { + PROVIDE (_alt_partition_onchip_memory2_0_start = ABSOLUTE(.)); + *(.onchip_memory2_0 .onchip_memory2_0. onchip_memory2_0.*) + . = ALIGN(4); + PROVIDE (_alt_partition_onchip_memory2_0_end = ABSOLUTE(.)); + _end = ABSOLUTE(.); + end = ABSOLUTE(.); + __alt_stack_base = ABSOLUTE(.); + } > onchip_memory2_0 + + PROVIDE (_alt_partition_onchip_memory2_0_load_addr = LOADADDR(.onchip_memory2_0)); + + /* + * Stabs debugging sections. + * + */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* Altera debug extensions */ + .debug_alt_sim_info 0 : { *(.debug_alt_sim_info) } +} + +/* provide a pointer for the stack */ + +/* + * Don't override this, override the __alt_stack_* symbols instead. + */ +__alt_data_end = 0x819000; + +/* + * The next two symbols define the location of the default stack. You can + * override them to move the stack to a different memory. + */ +PROVIDE( __alt_stack_pointer = __alt_data_end ); +PROVIDE( __alt_stack_limit = __alt_stack_base ); + +/* + * This symbol controls where the start of the heap is. If the stack is + * contiguous with the heap then the stack will contract as memory is + * allocated to the heap. + * Override this symbol to put the heap in a different memory. + */ +PROVIDE( __alt_heap_start = end ); +PROVIDE( __alt_heap_limit = 0x819000 ); diff --git a/software/sys_controller_bsp/mem_init.mk b/software/sys_controller_bsp/mem_init.mk new file mode 100644 index 0000000..5f0d286 --- /dev/null +++ b/software/sys_controller_bsp/mem_init.mk @@ -0,0 +1,362 @@ + +######################################################################### +####### M E M I N I T M A K E F I L E C O N T E N T ###### +######################################################################### + +######################################################################### +# This file is intended to be included by public.mk +# +# +# The following variables must be defined before including this file: +# - ELF +# +# The following variables may be defined to override the default behavior: +# - HDL_SIM_DIR +# - HDL_SIM_INSTALL_DIR +# - MEM_INIT_DIR +# - MEM_INIT_INSTALL_DIR +# - QUARTUS_PROJECT_DIR +# - SOPC_NAME +# - SIM_OPTIMIZE +# - RESET_ADDRESS +# +######################################################################### + +ifeq ($(MEM_INIT_FILE),) +# MEM_INIT_FILE should be set equal to the working relative path to this +# mem_init.mk makefile fragment +MEM_INIT_FILE := $(wildcard $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))) +endif + +ifeq ($(ELF2DAT),) +ELF2DAT := elf2dat +endif + +ifeq ($(ELF2HEX),) +ELF2HEX := elf2hex +endif + +ifeq ($(ELF2FLASH),) +ELF2FLASH := elf2flash +endif + +ifeq ($(FLASH2DAT),) +FLASH2DAT := flash2dat +endif + +ifeq ($(ALT_FILE_CONVERT),) +ALT_FILE_CONVERT := alt-file-convert +endif + +ifeq ($(NM),) +NM := nios2-elf-nm +endif + +ifeq ($(MKDIR),) +MKDIR := mkdir -p +endif + +ifeq ($(RM),) +RM := rm -f +endif + +ifeq ($(CP),) +CP := cp +endif + +ifeq ($(ECHO),) +ECHO := echo +endif + +MEM_INIT_DIR ?= mem_init +HDL_SIM_DIR ?= $(MEM_INIT_DIR)/hdl_sim + +ifdef QUARTUS_PROJECT_DIR +MEM_INIT_INSTALL_DIR ?= $(patsubst %/,%,$(QUARTUS_PROJECT_DIR)) +ifdef SOPC_NAME +HDL_SIM_INSTALL_DIR ?= $(patsubst %/,%,$(QUARTUS_PROJECT_DIR))/$(SOPC_NAME)_sim +endif +endif + +MEM_INIT_DESCRIPTOR_FILE ?= $(MEM_INIT_DIR)/meminit.spd + +MEM_INIT_QIP_FILE ?= $(MEM_INIT_DIR)/meminit.qip + +#------------------------------------- +# Default Flash Boot Loaders +#------------------------------------- + +BOOT_LOADER_PATH ?= $(SOPC_KIT_NIOS2)/components/altera_nios2 +BOOT_LOADER_CFI ?= $(BOOT_LOADER_PATH)/boot_loader_cfi.srec +BOOT_LOADER_CFI_BE ?= $(BOOT_LOADER_PATH)/boot_loader_cfi_be.srec + + +#------------------------------------- +# Default Target +#------------------------------------- + +.PHONY: default_mem_init +ifeq ($(QSYS),1) +default_mem_init: mem_init_generate +else +default_mem_init: mem_init_install +endif +#------------------------------------- +# Runtime Macros +#------------------------------------- + +define post-process-info + @echo Post-processing to create $@... +endef + +target_stem = $(notdir $(basename $@)) + +mem_start_address = $($(target_stem)_START) +mem_end_address = $($(target_stem)_END) +mem_span = $($(target_stem)_SPAN) +mem_width = $($(target_stem)_WIDTH) +mem_hex_width = $($(target_stem)_HEX_DATA_WIDTH) +mem_endianness = $($(target_stem)_ENDIANNESS) +mem_create_lanes = $($(target_stem)_CREATE_LANES) + +mem_pad_flag = $($(target_stem)_PAD_FLAG) +mem_reloc_input_flag = $($(target_stem)_RELOC_INPUT_FLAG) +mem_no_zero_fill_flag = $($(target_stem)_NO_ZERO_FILL_FLAG) + +flash_mem_epcs_flag = $($(target_stem)_EPCS_FLAGS) +flash_mem_cfi_flag = $($(target_stem)_CFI_FLAGS) +flash_mem_boot_loader_flag = $($(target_stem)_BOOT_LOADER_FLAG) + +elf2dat_extra_args = $(mem_pad_flag) +elf2hex_extra_args = $(mem_no_zero_fill_flag) +elf2flash_extra_args = $(flash_mem_cfi_flag) $(flash_mem_epcs_flag) $(flash_mem_boot_loader_flag) +flash2dat_extra_args = $(mem_pad_flag) $(mem_reloc_input_flag) + +#------------------------------------------------------------------------------ +# BSP SPECIFIC CONTENT +# +# The content below is controlled by the BSP and SOPC System +#------------------------------------------------------------------------------ +#START OF BSP SPECIFIC + +#------------------------------------- +# Global Settings +#------------------------------------- + + +# The following TYPE comment allows tools to identify the 'type' of target this +# makefile is associated with. +# TYPE: BSP_MEMINIT_MAKEFILE + +# This following VERSION comment indicates the version of the tool used to +# generate this makefile. A makefile variable is provided for VERSION as well. +# ACDS_VERSION: 15.1 +ACDS_VERSION := 15.1 + +# This following BUILD_NUMBER comment indicates the build number of the tool +# used to generate this makefile. +# BUILD_NUMBER: 185 + +# Optimize for simulation +SIM_OPTIMIZE ?= 0 + +# The CPU reset address as needed by elf2flash +RESET_ADDRESS ?= 0x00810000 + +# The specific Nios II ELF file format to use. +NIOS2_ELF_FORMAT ?= elf32-littlenios2 + +#------------------------------------- +# Pre-Initialized Memory Descriptions +#------------------------------------- + +# Memory: epcq_controller_0 +MEM_0 := epcq_controller_0 +$(MEM_0)_NAME := epcq_controller_0 +HEX_FILES += $(MEM_INIT_DIR)/$(MEM_0).hex +MEM_INIT_INSTALL_FILES += $(MEM_INIT_INSTALL_DIR)/$(MEM_0).hex +$(MEM_0)_START := 0x00000000 +$(MEM_0)_END := 0x007fffff +$(MEM_0)_SPAN := 0x00800000 +$(MEM_0)_HIERARCHICAL_PATH := epcq_controller_0 +$(MEM_0)_WIDTH := 32 +$(MEM_0)_HEX_DATA_WIDTH := 8 +$(MEM_0)_ENDIANNESS := --little-endian-mem +$(MEM_0)_CREATE_LANES := 0 +$(MEM_0)_CFI_FLAGS := --base=$($(MEM_0)_START) --end=$($(MEM_0)_END) --reset=$(RESET_ADDRESS) + +.PHONY: epcq_controller_0 +epcq_controller_0: check_elf_exists $(MEM_INIT_DIR)/$(MEM_0).hex + +# Memory: onchip_memory2_0 +MEM_1 := sys_onchip_memory2_0 +$(MEM_1)_NAME := onchip_memory2_0 +$(MEM_1)_MEM_INIT_FILE_PARAM_NAME := INIT_FILE +HEX_FILES += $(MEM_INIT_DIR)/$(MEM_1).hex +MEM_INIT_INSTALL_FILES += $(MEM_INIT_INSTALL_DIR)/$(MEM_1).hex +DAT_FILES += $(HDL_SIM_DIR)/$(MEM_1).dat +HDL_SIM_INSTALL_FILES += $(HDL_SIM_INSTALL_DIR)/$(MEM_1).dat +SYM_FILES += $(HDL_SIM_DIR)/$(MEM_1).sym +HDL_SIM_INSTALL_FILES += $(HDL_SIM_INSTALL_DIR)/$(MEM_1).sym +$(MEM_1)_START := 0x00810000 +$(MEM_1)_END := 0x00818fff +$(MEM_1)_SPAN := 0x00009000 +$(MEM_1)_HIERARCHICAL_PATH := onchip_memory2_0 +$(MEM_1)_WIDTH := 32 +$(MEM_1)_HEX_DATA_WIDTH := 32 +$(MEM_1)_ENDIANNESS := --little-endian-mem +$(MEM_1)_CREATE_LANES := 0 + +.PHONY: onchip_memory2_0 +onchip_memory2_0: check_elf_exists $(MEM_INIT_DIR)/$(MEM_1).hex $(HDL_SIM_DIR)/$(MEM_1).dat $(HDL_SIM_DIR)/$(MEM_1).sym + + +#END OF BSP SPECIFIC + +#------------------------------------- +# Pre-Initialized Memory Targets +#------------------------------------- + +.PHONY: mem_init_install mem_init_generate mem_init_clean + +ifeq ($(QSYS),1) +# Target mem_init_install is deprecated for QSys based systems +# To initialize onchip memories for Quartus II Synthesis with Qsys based systems: +# 1) Use "make mem_init_genearate" +# 2) Add the generated mem_init/meminit.qip file to your Quartus II Project +# +mem_init_install: + $(error Deprecated Makefile Target: '$@'. Use target 'mem_init_generate' and then add $(MEM_INIT_QIP_FILE) to your Quartus II Project) + +else # QSYS != 1, if SopcBuilder based system + +ifneq ($(MEM_INIT_INSTALL_DIR),) +mem_init_install: $(MEM_INIT_INSTALL_FILES) +endif + +ifneq ($(HDL_SIM_INSTALL_DIR),) +mem_init_install: $(HDL_SIM_INSTALL_FILES) +endif + +mem_init_install: mem_init_generate +ifeq ($(MEM_INIT_INSTALL_DIR),) + @echo "WARNING: MEM_INIT_INSTALL_DIR not set. Set your QUARTUS_PROJECT_DIR environment variable." +endif +ifeq ($(HDL_SIM_INSTALL_DIR),) + @echo "WARNING: HDL_SIM_INSTALL_DIR not set. Set your QUARTUS_PROJECT_DIR and SOPC_NAME environment variable." +endif + +$(MEM_INIT_INSTALL_FILES): $(MEM_INIT_INSTALL_DIR)/%: $(MEM_INIT_DIR)/% + @$(MKDIR) $(@D) + @$(CP) -v $< $@ + +$(HDL_SIM_INSTALL_FILES): $(HDL_SIM_INSTALL_DIR)/%: $(HDL_SIM_DIR)/% + @$(MKDIR) $(@D) + @$(CP) -v $< $@ + +endif # QSYS == 1 + + +mem_init_generate: hex dat sym flash $(MEM_INIT_DESCRIPTOR_FILE) $(MEM_INIT_QIP_FILE) + +mem_init_clean: + @$(RM) -r $(MEM_INIT_DIR) $(HDL_SIM_DIR) $(FLASH_FILES) + +.PHONY: hex dat sym flash + +hex: check_elf_exists $(HEX_FILES) + +dat: check_elf_exists $(DAT_FILES) + +sym: check_elf_exists $(SYM_FILES) + +flash: check_elf_exists $(FLASH_FILES) + +#------------------------------------- +# Pre-Initialized Memory Rules +#------------------------------------- + +.PHONY: check_elf_exists +check_elf_exists: $(ELF) +ifeq ($(ELF),) + $(error ELF var not set in mem_init.mk) +endif + +$(filter-out $(FLASH_DAT_FILES),$(DAT_FILES)): %.dat: $(ELF) + $(post-process-info) + @$(MKDIR) $(@D) + $(ELF2DAT) --infile=$< --outfile=$@ \ + --base=$(mem_start_address) --end=$(mem_end_address) --width=$(mem_width) \ + $(mem_endianness) --create-lanes=$(mem_create_lanes) $(elf2dat_extra_args) + +$(foreach i,0 1 2 3 4 5 6 7,%_lane$(i).dat): %.dat + @true + +ELF_TO_HEX_CMD_NO_BOOTLOADER = $(ELF2HEX) $< $(mem_start_address) $(mem_end_address) --width=$(mem_hex_width) \ + $(mem_endianness) --create-lanes=$(mem_create_lanes) $(elf2hex_extra_args) $@ + +ELF_TO_HEX_CMD_WITH_BOOTLOADER = $(ALT_FILE_CONVERT) -I $(NIOS2_ELF_FORMAT) -O hex --input=$< --output=$@ \ + --base=$(mem_start_address) --end=$(mem_end_address) --reset=$(RESET_ADDRESS) \ + --out-data-width=$(mem_hex_width) $(flash_mem_boot_loader_flag) + +ELF_TO_HEX_CMD = $(strip $(if $(flash_mem_boot_loader_flag), \ + $(ELF_TO_HEX_CMD_WITH_BOOTLOADER), \ + $(ELF_TO_HEX_CMD_NO_BOOTLOADER) \ + )) + +$(HEX_FILES): %.hex: $(ELF) + $(post-process-info) + @$(MKDIR) $(@D) + $(ELF_TO_HEX_CMD) + +$(SYM_FILES): %.sym: $(ELF) + $(post-process-info) + @$(MKDIR) $(@D) + $(NM) -n $< > $@ + +$(FLASH_FILES): %.flash: $(ELF) + $(post-process-info) + @$(MKDIR) $(@D) + $(ELF2FLASH) --input=$< --outfile=$@ --sim_optimize=$(SIM_OPTIMIZE) $(mem_endianness) \ + $(elf2flash_extra_args) + +# +# Function generate_spd_entry +# Arg1: path to the memory initialization file +# Arg2: Type HEX or DAT +# Arg3: Output spd file to append +gen_spd_entry.BASE_FILE = $(basename $(notdir $1)) +gen_spd_entry.PARAM_NAME = $($(gen_spd_entry.BASE_FILE)_MEM_INIT_FILE_PARAM_NAME) +gen_spd_entry.MEM_PATH = $($(gen_spd_entry.BASE_FILE)_HIERARCHICAL_PATH) +gen_spd_entry.SETTINGS = $(strip \ + path=\"$1\" \ + type=\"$2\" \ + $(if $(gen_spd_entry.PARAM_NAME),initParamName=\"$(gen_spd_entry.PARAM_NAME)\") \ + $(if $(gen_spd_entry.MEM_PATH),memoryPath=\"$(gen_spd_entry.MEM_PATH)\") \ +) +define gen_spd_entry +$(ECHO) "" >> $3 +endef + +$(MEM_INIT_DESCRIPTOR_FILE).DAT_FILESET := $(patsubst $(dir $(MEM_INIT_DESCRIPTOR_FILE))%,%,$(DAT_FILES)) +$(MEM_INIT_DESCRIPTOR_FILE).HEX_FILESET := $(patsubst $(dir $(MEM_INIT_DESCRIPTOR_FILE))%,%,$(HEX_FILES)) + +$(MEM_INIT_DESCRIPTOR_FILE): %.spd: $(MEM_INIT_FILE) + $(post-process-info) + @$(MKDIR) $(@D) + @$(RM) $@ + @$(ECHO) "" > $@ + @$(ECHO) "" >> $@ + @$(foreach dat_file,$($@.DAT_FILESET),$(call gen_spd_entry,$(dat_file),DAT,$@) &&)true + @$(foreach hex_file,$($@.HEX_FILESET),$(call gen_spd_entry,$(hex_file),HEX,$@) &&)true + @$(ECHO) "" >> $@ + +.DELETE_ON_ERROR: $(MEM_INIT_DESCRIPTOR_FILE) + +$(MEM_INIT_QIP_FILE): %.qip: $(MEM_INIT_FILE) + $(post-process-info) + @$(MKDIR) $(@D) + @$(RM) $@ + @$(ECHO) "set_global_assignment -name SEARCH_PATH $$::quartus(qip_path)" > $@ + +.DELETE_ON_ERROR: $(MEM_INIT_QIP_FILE) diff --git a/software/sys_controller_bsp/memory.gdb b/software/sys_controller_bsp/memory.gdb new file mode 100644 index 0000000..a7365f0 --- /dev/null +++ b/software/sys_controller_bsp/memory.gdb @@ -0,0 +1,53 @@ +# memory.gdb - GDB memory region definitions +# +# Machine generated for CPU 'nios2_qsys_0' in SOPC Builder design 'sys' +# SOPC Builder design path: ../../sys.sopcinfo +# +# Generated: Sun May 03 12:35:19 EEST 2015 + +# DO NOT MODIFY THIS FILE +# +# Changing this file will have subtle consequences +# which will almost certainly lead to a nonfunctioning +# system. If you do modify this file, be aware that your +# changes will be overwritten and lost when this file +# is generated again. +# +# DO NOT MODIFY THIS FILE + +# License Agreement +# +# Copyright (c) 2008 +# Altera Corporation, San Jose, California, USA. +# All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# This agreement shall be governed in all respects by the laws of the State +# of California and by the laws of the United States of America. + +# Define memory regions for each memory connected to the CPU. +# The cache attribute is specified which improves GDB performance +# by allowing GDB to cache memory contents on the host. + +# epcq_controller_0_avl_mem +memory 0x0 0x800000 cache + +# onchip_memory2_0 +memory 0x810000 0x819000 cache diff --git a/software/sys_controller_bsp/public.mk b/software/sys_controller_bsp/public.mk new file mode 100644 index 0000000..d5f404e --- /dev/null +++ b/software/sys_controller_bsp/public.mk @@ -0,0 +1,400 @@ +#------------------------------------------------------------------------------ +# BSP "PUBLIC" MAKEFILE CONTENT +# +# This file is intended to be included in an application or library +# Makefile that is using this BSP. You can create such a Makefile with +# the nios2-app-generate-makefile or nios2-lib-generate-makefile +# commands. +# +# The following variables must be defined before including this file: +# +# ALT_LIBRARY_ROOT_DIR +# Contains the path to the BSP top-level (aka root) directory +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# PATHS +#------------------------------------------------------------------------------ + + + +# Path to the provided linker script. +BSP_LINKER_SCRIPT := $(ALT_LIBRARY_ROOT_DIR)/linker.x + +# Include paths: +# The path to root of all header files that a library wishes to make +# available for an application's use is specified here. Note that this +# may not be *all* folders within a hierarchy. For example, if it is +# desired that the application developer type: +# #include +# #include +# With files laid out like this: +# /inc/sockets.h +# /inc/ip/tcpip.h +# +# Then, only /inc need be added to the list of include +# directories. Alternatively, if you wish to be able to directly include +# all files in a hierarchy, separate paths to each folder in that +# hierarchy must be defined. + +# The following are the "base" set of include paths for a BSP. +# These paths are appended to the list that individual software +# components, drivers, etc., add in the generated portion of this +# file (below). +ALT_INCLUDE_DIRS_TO_APPEND += \ + $(ALT_LIBRARY_ROOT_DIR) \ + $(ALT_LIBRARY_ROOT_DIR)/drivers/inc + +# Additions to linker library search-path: +# Here we provide a path to "our self" for the application to construct a +# "-L " out of. This should contain a list of directories, +# relative to the library root, of all directories with .a files to link +# against. +ALT_LIBRARY_DIRS += $(ALT_LIBRARY_ROOT_DIR) + + +#------------------------------------------------------------------------------ +# COMPILATION FLAGS +#------------------------------------------------------------------------------ +# Default C pre-processor flags for a BSP: +ALT_CPPFLAGS += -pipe + + +#------------------------------------------------------------------------------ +# MANAGED CONTENT +# +# All content between the lines "START MANAGED" and "END MANAGED" below is +# generated based on variables in the BSP settings file when the +# nios2-bsp-generate-files command is invoked. If you wish to persist any +# information pertaining to the build process, it is recomended that you +# utilize the BSP settings mechanism to do so. +#------------------------------------------------------------------------------ +#START MANAGED + +# The following TYPE comment allows tools to identify the 'type' of target this +# makefile is associated with. +# TYPE: BSP_PUBLIC_MAKEFILE + +# This following VERSION comment indicates the version of the tool used to +# generate this makefile. A makefile variable is provided for VERSION as well. +# ACDS_VERSION: 15.1 +ACDS_VERSION := 15.1 + +# This following BUILD_NUMBER comment indicates the build number of the tool +# used to generate this makefile. +# BUILD_NUMBER: 185 + +# Qsys--generated SOPCINFO file. Required for resolving node instance ID's with +# design component names. +SOPCINFO_FILE := $(ABS_BSP_ROOT_DIR)/../../sys.sopcinfo + +# Big-Endian operation. +# setting BIG_ENDIAN is false + + +# BMX present. +# setting BMX is false + +# Path to the provided C language runtime initialization code. +BSP_CRT0 := $(ALT_LIBRARY_ROOT_DIR)/obj/HAL/src/crt0.o + +# Name of BSP library as provided to linker using the "-msys-lib" flag or +# linker script GROUP command. +# setting BSP_SYS_LIB is hal_bsp +BSP_SYS_LIB := hal_bsp +ELF_PATCH_FLAG += --thread_model hal + +# Type identifier of the BSP library +# setting BSP_TYPE is hal +ALT_CPPFLAGS += -D__hal__ +BSP_TYPE := hal + +# CDX present. +# setting CDX is false + +# CPU Name +# setting CPU_NAME is nios2_qsys_0 +CPU_NAME = nios2_qsys_0 +ELF_PATCH_FLAG += --cpu_name $(CPU_NAME) + +# Hardware Divider present. +# setting HARDWARE_DIVIDE is false +ALT_CFLAGS += -mno-hw-div + +# Hardware Multiplier present. +# setting HARDWARE_MULTIPLY is false +ALT_CFLAGS += -mno-hw-mul + +# Hardware Mulx present. +# setting HARDWARE_MULX is false +ALT_CFLAGS += -mno-hw-mulx + +# Debug Core present. +# setting HAS_DEBUG_CORE is true +CPU_HAS_DEBUG_CORE = 1 + +# Qsys generated design +# setting QSYS is 1 +QSYS := 1 +ELF_PATCH_FLAG += --qsys true + +# Design Name +# setting SOPC_NAME is sys +SOPC_NAME := sys + +# SopcBuilder Simulation Enabled +# setting SOPC_SIMULATION_ENABLED is false +ELF_PATCH_FLAG += --simulation_enabled false + +# Enable JTAG UART driver to recover when host is inactive causing buffer to +# full without returning error. Printf will not fail with this recovery. none +# setting altera_avalon_jtag_uart_driver.enable_jtag_uart_ignore_fifo_full_error is true + +# Small-footprint (polled mode) driver none +# setting altera_avalon_jtag_uart_driver.enable_small_driver is false + +# Build a custom version of newlib with the specified space-separated compiler +# flags. The custom newlib build will be placed in the /newlib +# directory, and will be used only for applications that utilize this BSP. +# setting hal.custom_newlib_flags is none + +# Enable support for a subset of the C++ language. This option increases code +# footprint by adding support for C++ constructors. Certain features, such as +# multiple inheritance and exceptions are not supported. If false, adds +# -DALT_NO_C_PLUS_PLUS to ALT_CPPFLAGS in public.mk, and reduces code +# footprint. none +# setting hal.enable_c_plus_plus is false +ALT_CPPFLAGS += -DALT_NO_C_PLUS_PLUS + +# When your application exits, close file descriptors, call C++ destructors, +# etc. Code footprint can be reduced by disabling clean exit. If disabled, adds +# -DALT_NO_CLEAN_EXIT to ALT_CPPFLAGS -D'exit(a)=_exit(a)' in public.mk. none +# setting hal.enable_clean_exit is false +ALT_CPPFLAGS += -DALT_NO_CLEAN_EXIT -D'exit(a)=_exit(a)' + +# Add exit() support. This option increases code footprint if your "main()" +# routine does "return" or call "exit()". If false, adds -DALT_NO_EXIT to +# ALT_CPPFLAGS in public.mk, and reduces footprint none +# setting hal.enable_exit is false +ALT_CPPFLAGS += -DALT_NO_EXIT + +# Causes code to be compiled with gprof profiling enabled and the application +# ELF to be linked with the GPROF library. If true, adds -DALT_PROVIDE_GMON to +# ALT_CPPFLAGS and -pg to ALT_CFLAGS in public.mk. none +# setting hal.enable_gprof is false + +# Enables lightweight device driver API. This reduces code and data footprint +# by removing the HAL layer that maps device names (e.g. /dev/uart0) to file +# descriptors. Instead, driver routines are called directly. The open(), +# close(), and lseek() routines will always fail if called. The read(), +# write(), fstat(), ioctl(), and isatty() routines only work for the stdio +# devices. If true, adds -DALT_USE_DIRECT_DRIVERS to ALT_CPPFLAGS in public.mk. +# The Altera Host and read-only ZIP file systems can't be used if +# hal.enable_lightweight_device_driver_api is true. +# setting hal.enable_lightweight_device_driver_api is false + +# Adds code to emulate multiply and divide instructions in case they are +# executed but aren't present in the CPU. Normally this isn't required because +# the compiler won't use multiply and divide instructions that aren't present +# in the CPU. If false, adds -DALT_NO_INSTRUCTION_EMULATION to ALT_CPPFLAGS in +# public.mk. none +# setting hal.enable_mul_div_emulation is false +ALT_CPPFLAGS += -DALT_NO_INSTRUCTION_EMULATION + +# Certain drivers are compiled with reduced functionality to reduce code +# footprint. Not all drivers observe this setting. The altera_avalon_uart and +# altera_avalon_jtag_uart drivers switch from interrupt-driven to polled +# operation. CAUTION: Several device drivers are disabled entirely. These +# include the altera_avalon_cfi_flash, altera_avalon_epcs_flash_controller, and +# altera_avalon_lcd_16207 drivers. This can result in certain API (HAL flash +# access routines) to fail. You can define a symbol provided by each driver to +# prevent it from being removed. If true, adds -DALT_USE_SMALL_DRIVERS to +# ALT_CPPFLAGS in public.mk. none +# setting hal.enable_reduced_device_drivers is true +ALT_CPPFLAGS += -DALT_USE_SMALL_DRIVERS + +# Turns on HAL runtime stack checking feature. Enabling this setting causes +# additional code to be placed into each subroutine call to generate an +# exception if a stack collision occurs with the heap or statically allocated +# data. If true, adds -DALT_STACK_CHECK and -fstack-limit-register=et to +# ALT_CPPFLAGS in public.mk. none +# setting hal.enable_runtime_stack_checking is false + +# The BSP is compiled with optimizations to speedup HDL simulation such as +# initializing the cache, clearing the .bss section, and skipping long delay +# loops. If true, adds -DALT_SIM_OPTIMIZE to ALT_CPPFLAGS in public.mk. When +# this setting is true, the BSP shouldn't be used to build applications that +# are expected to run real hardware. +# setting hal.enable_sim_optimize is false + +# Causes the small newlib (C library) to be used. This reduces code and data +# footprint at the expense of reduced functionality. Several newlib features +# are removed such as floating-point support in printf(), stdin input routines, +# and buffered I/O. The small C library is not compatible with Micrium +# MicroC/OS-II. If true, adds -msmallc to ALT_LDFLAGS in public.mk. none +# setting hal.enable_small_c_library is true +ALT_LDFLAGS += -msmallc +ALT_CPPFLAGS += -DSMALL_C_LIB + +# Enable SOPC Builder System ID. If a System ID SOPC Builder component is +# connected to the CPU associated with this BSP, it will be enabled in the +# creation of command-line arguments to download an ELF to the target. +# Otherwise, system ID and timestamp values are left out of public.mk for +# application Makefile "download-elf" target definition. With the system ID +# check disabled, the Nios II EDS tools will not automatically ensure that the +# application .elf file (and BSP it is linked against) corresponds to the +# hardware design on the target. If false, adds --accept-bad-sysid to +# SOPC_SYSID_FLAG in public.mk. none +# setting hal.enable_sopc_sysid_check is true + +# Enable BSP generation to query if SOPC system is big endian. If true ignores +# export of 'ALT_CFLAGS += -meb' to public.mk if big endian system. none +# setting hal.make.ignore_system_derived.big_endian is false + +# If true, prevents GCC from using BMX instructions. If false, GCC uses BMX +# instructions if present in the CPU. none +# setting hal.make.ignore_system_derived.bmx_present is false + +# If true, prevents GCC from using CDX instructions. If false, GCC uses CDX +# instructions if present in the CPU. none +# setting hal.make.ignore_system_derived.cdx_present is false + +# Enable BSP generation to query if SOPC system has a debug core present. If +# true ignores export of 'CPU_HAS_DEBUG_CORE = 1' to public.mk if a debug core +# is found in the system. If true ignores export of 'CPU_HAS_DEBUG_CORE = 0' if +# no debug core is found in the system. none +# setting hal.make.ignore_system_derived.debug_core_present is false + +# Enable BSP generation to query if SOPC system has FPU present. If true +# ignores export of 'ALT_CFLAGS += -mhard-float' to public.mk if FPU is found +# in the system. If true ignores export of 'ALT_CFLAGS += -mhard-soft' if FPU +# is not found in the system. none +# setting hal.make.ignore_system_derived.fpu_present is false + +# Enable BSP generation to query if SOPC system has hardware divide present. If +# true ignores export of 'ALT_CFLAGS += -mno-hw-div' to public.mk if no +# division is found in system. If true ignores export of 'ALT_CFLAGS += +# -mhw-div' if division is found in the system. none +# setting hal.make.ignore_system_derived.hardware_divide_present is false + +# Enable BSP generation to query if SOPC system floating point custom +# instruction with a divider is present. If true ignores export of 'ALT_CFLAGS +# += -mcustom-fpu-cfg=60-2' and 'ALT_LDFLAGS += -mcustom-fpu-cfg=60-2' to +# public.mk if the custom instruction is found in the system. none +# setting hal.make.ignore_system_derived.hardware_fp_cust_inst_divider_present is false + +# Enable BSP generation to query if SOPC system floating point custom +# instruction without a divider is present. If true ignores export of +# 'ALT_CFLAGS += -mcustom-fpu-cfg=60-1' and 'ALT_LDFLAGS += +# -mcustom-fpu-cfg=60-1' to public.mk if the custom instruction is found in the +# system. none +# setting hal.make.ignore_system_derived.hardware_fp_cust_inst_no_divider_present is false + +# Enable BSP generation to query if SOPC system has multiplier present. If true +# ignores export of 'ALT_CFLAGS += -mno-hw-mul' to public.mk if no multiplier +# is found in the system. If true ignores export of 'ALT_CFLAGS += -mhw-mul' if +# multiplier is found in the system. none +# setting hal.make.ignore_system_derived.hardware_multiplier_present is false + +# Enable BSP generation to query if SOPC system has hardware mulx present. If +# true ignores export of 'ALT_CFLAGS += -mno-hw-mulx' to public.mk if no mulx +# is found in the system. If true ignores export of 'ALT_CFLAGS += -mhw-mulx' +# if mulx is found in the system. none +# setting hal.make.ignore_system_derived.hardware_mulx_present is false + +# Enable BSP generation to query if SOPC system has simulation enabled. If true +# ignores export of 'ELF_PATCH_FLAG += --simulation_enabled' to public.mk. none +# setting hal.make.ignore_system_derived.sopc_simulation_enabled is false + +# Enable BSP generation to query SOPC system for system ID base address. If +# true ignores export of 'SOPC_SYSID_FLAG += --sidp=

' and +# 'ELF_PATCH_FLAG += --sidp=
' to public.mk. none +# setting hal.make.ignore_system_derived.sopc_system_base_address is false + +# Enable BSP generation to query SOPC system for system ID. If true ignores +# export of 'SOPC_SYSID_FLAG += --id=' and 'ELF_PATCH_FLAG += +# --id=' to public.mk. none +# setting hal.make.ignore_system_derived.sopc_system_id is false + +# Enable BSP generation to query SOPC system for system timestamp. If true +# ignores export of 'SOPC_SYSID_FLAG += --timestamp=' and +# 'ELF_PATCH_FLAG += --timestamp=' to public.mk. none +# setting hal.make.ignore_system_derived.sopc_system_timestamp is false + +# Slave descriptor of STDERR character-mode device. This setting is used by the +# ALT_STDERR family of defines in system.h. none +# setting hal.stderr is jtag_uart_0 +ELF_PATCH_FLAG += --stderr_dev jtag_uart_0 + +# Slave descriptor of STDIN character-mode device. This setting is used by the +# ALT_STDIN family of defines in system.h. none +# setting hal.stdin is jtag_uart_0 +ELF_PATCH_FLAG += --stdin_dev jtag_uart_0 + +# Slave descriptor of STDOUT character-mode device. This setting is used by the +# ALT_STDOUT family of defines in system.h. none +# setting hal.stdout is jtag_uart_0 +ELF_PATCH_FLAG += --stdout_dev jtag_uart_0 + + +#------------------------------------------------------------------------------ +# SOFTWARE COMPONENT & DRIVER INCLUDE PATHS +#------------------------------------------------------------------------------ + +ALT_INCLUDE_DIRS += $(ALT_LIBRARY_ROOT_DIR)/HAL/inc + +#------------------------------------------------------------------------------ +# SOFTWARE COMPONENT & DRIVER PRODUCED ALT_CPPFLAGS ADDITIONS +#------------------------------------------------------------------------------ + +ALT_CPPFLAGS += -DALT_SINGLE_THREADED + +#------------------------------------------------------------------------------ +# SOFTWARE COMPONENT & DRIVER SETTING-PRODUCED DEFINITIONS +#------------------------------------------------------------------------------ + +ALT_CPPFLAGS += -DALTERA_AVALON_JTAG_UART_IGNORE_FIFO_FULL_ERROR + +#END MANAGED + + +#------------------------------------------------------------------------------ +# LIBRARY INFORMATION +#------------------------------------------------------------------------------ +# Assemble the name of the BSP *.a file using the BSP library name +# (BSP_SYS_LIB) in generated content above. +BSP_LIB := lib$(BSP_SYS_LIB).a + +# Additional libraries to link against: +# An application including this file will prefix each library with "-l". +# For example, to include the Newlib math library "m" is included, which +# becomes "-lm" when linking the application. +ALT_LIBRARY_NAMES += m + +# Additions to linker dependencies: +# An application Makefile will typically add these directly to the list +# of dependencies required to build the executable target(s). The BSP +# library (*.a) file is specified here. +ALT_LDDEPS += $(ALT_LIBRARY_ROOT_DIR)/$(BSP_LIB) + +# Is this library "Makeable"? +# Add to list of root library directories that support running 'make' +# to build them. Because libraries may or may not have a Makefile in their +# root, appending to this variable tells an application to run 'make' in +# the library root to build/update this library. +MAKEABLE_LIBRARY_ROOT_DIRS += $(ALT_LIBRARY_ROOT_DIR) + +# Additional Assembler Flags +# -gdwarf2 flag is required for stepping through assembly code +ALT_ASFLAGS += -gdwarf2 + +#------------------------------------------------------------------------------ +# FINAL INCLUDE PATH LIST +#------------------------------------------------------------------------------ +# Append static include paths to paths specified by OS/driver/sw package +# additions to the BSP thus giving them precedence in case a BSP addition +# is attempting to override BSP sources. +ALT_INCLUDE_DIRS += $(ALT_INCLUDE_DIRS_TO_APPEND) + + + diff --git a/software/sys_controller_bsp/settings.bsp b/software/sys_controller_bsp/settings.bsp new file mode 100644 index 0000000..3a768c6 --- /dev/null +++ b/software/sys_controller_bsp/settings.bsp @@ -0,0 +1,985 @@ + + + hal + default + Feb 18, 2016 1:07:07 AM + 1455750427597 + ./ + ../sys_controller_bsp/settings.bsp + ../../sys.sopcinfo + default + nios2_qsys_0 + 1.9 + + hal.sys_clk_timer + ALT_SYS_CLK + UnquotedString + none + none + system_h_define + Slave descriptor of the system clock timer device. This device provides a periodic interrupt ("tick") and is typically required for RTOS use. This setting defines the value of ALT_SYS_CLK in system.h. + none + false + common + + + hal.timestamp_timer + ALT_TIMESTAMP_CLK + UnquotedString + none + none + system_h_define + Slave descriptor of timestamp timer device. This device is used by Altera HAL timestamp drivers for high-resolution time measurement. This setting defines the value of ALT_TIMESTAMP_CLK in system.h. + none + false + common + + + hal.max_file_descriptors + ALT_MAX_FD + DecimalNumber + 32 + 32 + system_h_define + Determines the number of file descriptors statically allocated. This setting defines the value of ALT_MAX_FD in system.h. + If hal.enable_lightweight_device_driver_api is true, there are no file descriptors so this setting is ignored. If hal.enable_lightweight_device_driver_api is false, this setting must be at least 4 because HAL needs a file descriptor for /dev/null, /dev/stdin, /dev/stdout, and /dev/stderr. + false + + + + hal.enable_instruction_related_exceptions_api + ALT_INCLUDE_INSTRUCTION_RELATED_EXCEPTION_API + BooleanDefineOnly + false + false + system_h_define + Enables API for registering handlers to service instruction-related exceptions. Enabling this setting increases the size of the exception entry code. + These exception types can be generated if various processor options are enabled, such as the MMU, MPU, or other advanced exception types. + false + + + + hal.linker.allow_code_at_reset + ALT_ALLOW_CODE_AT_RESET + Boolean + 1 + 0 + none + Indicates if initialization code is allowed at the reset address. If true, defines the macro ALT_ALLOW_CODE_AT_RESET in linker.h. + If true, defines the macro ALT_ALLOW_CODE_AT_RESET in linker.h. This setting is typically false if an external bootloader (e.g. flash bootloader) is present. + false + + + + hal.linker.enable_alt_load + none + Boolean + 1 + 0 + none + Enables the alt_load() facility. The alt_load() facility copies sections from the .text memory into RAM. If true, this setting sets up the VMA/LMA of sections in linker.x to allow them to be loaded into the .text memory. + This setting is typically false if an external bootloader (e.g. flash bootloader) is present. + false + + + + hal.linker.enable_alt_load_copy_rodata + none + Boolean + 0 + 0 + none + Causes the alt_load() facility to copy the .rodata section. If true, this setting defines the macro ALT_LOAD_COPY_RODATA in linker.h. + none + false + + + + hal.linker.enable_alt_load_copy_rwdata + none + Boolean + 1 + 0 + none + Causes the alt_load() facility to copy the .rwdata section. If true, this setting defines the macro ALT_LOAD_COPY_RWDATA in linker.h. + none + false + + + + hal.linker.enable_alt_load_copy_exceptions + none + Boolean + 0 + 0 + none + Causes the alt_load() facility to copy the .exceptions section. If true, this setting defines the macro ALT_LOAD_COPY_EXCEPTIONS in linker.h. + none + false + + + + hal.linker.enable_exception_stack + none + Boolean + 0 + 0 + none + Enables use of a separate exception stack. If true, defines the macro ALT_EXCEPTION_STACK in linker.h, adds a memory region called exception_stack to linker.x, and provides the symbols __alt_exception_stack_pointer and __alt_exception_stack_limit in linker.x. + The hal.linker.exception_stack_size and hal.linker.exception_stack_memory_region_name settings must also be valid. This setting must be false for MicroC/OS-II BSPs. The exception stack can be used to improve interrupt and other exception performance if the EIC is *not* used. + false + common + + + hal.linker.exception_stack_size + none + DecimalNumber + 1024 + 1024 + none + Size of the exception stack in bytes. + Only used if hal.linker.enable_exception_stack is true. + false + common + + + hal.linker.exception_stack_memory_region_name + none + UnquotedString + onchip_memory2_0 + none + none + Name of the existing memory region that will be divided up to create the 'exception_stack' memory region. The selected region name will be adjusted automatically when the BSP is generated to create the 'exception_stack' memory region. + Only used if hal.linker.enable_exception_stack is true. + false + common + + + hal.linker.enable_interrupt_stack + none + Boolean + 0 + 0 + none + Enables use of a separate interrupt stack. If true, defines the macro ALT_INTERRUPT_STACK in linker.h, adds a memory region called interrupt_stack to linker.x, and provides the symbols __alt_interrupt_stack_pointer and __alt_interrupt_stack_limit in linker.x. + The hal.linker.interrupt_stack_size and hal.linker.interrupt_stack_memory_region_name settings must also be valid. This setting must be false for MicroC/OS-II BSPs. Only enable if the EIC is used exclusively. The exception stack can be used to improve interrupt and other exception performance if the EIC is *not* used. + false + common + + + hal.linker.interrupt_stack_size + none + DecimalNumber + 1024 + 1024 + none + Size of the interrupt stack in bytes. + Only used if hal.linker.enable_interrupt_stack is true. + false + common + + + hal.linker.interrupt_stack_memory_region_name + none + UnquotedString + onchip_memory2_0 + none + none + Name of the existing memory region that will be divided up to create the 'interrupt_stack' memory region. The selected region name will be adjusted automatically when the BSP is generated to create the 'interrupt_stack' memory region. + Only used if hal.linker.enable_interrupt_stack is true. + false + common + + + hal.stdin + none + UnquotedString + jtag_uart_0 + none + system_h_define + Slave descriptor of STDIN character-mode device. This setting is used by the ALT_STDIN family of defines in system.h. + none + false + common + + + hal.stdout + none + UnquotedString + jtag_uart_0 + none + system_h_define + Slave descriptor of STDOUT character-mode device. This setting is used by the ALT_STDOUT family of defines in system.h. + none + false + common + + + hal.stderr + none + UnquotedString + jtag_uart_0 + none + system_h_define + Slave descriptor of STDERR character-mode device. This setting is used by the ALT_STDERR family of defines in system.h. + none + false + common + + + hal.log_port + none + UnquotedString + none + none + public_mk_define + Slave descriptor of debug logging character-mode device. If defined, it enables extra debug messages in the HAL source. This setting is used by the ALT_LOG_PORT family of defines in system.h. + none + false + none + + + hal.make.build_pre_process + BUILD_PRE_PROCESS + UnquotedString + none + none + makefile_variable + Command executed before BSP built. + none + false + none + + + hal.make.ar_pre_process + AR_PRE_PROCESS + UnquotedString + none + none + makefile_variable + Command executed before archiver execution. + none + false + none + + + hal.make.bsp_cflags_defined_symbols + BSP_CFLAGS_DEFINED_SYMBOLS + UnquotedString + none + none + makefile_variable + Preprocessor macros to define. A macro definition in this setting has the same effect as a "#define" in source code. Adding "-DALT_DEBUG" to this setting has the same effect as "#define ALT_DEBUG" in a souce file. Adding "-DFOO=1" to this setting is equivalent to the macro "#define FOO 1" in a source file. Macros defined with this setting are applied to all .S, .c, and C++ files in the BSP. This setting defines the value of BSP_CFLAGS_DEFINED_SYMBOLS in the BSP Makefile. + none + false + none + + + hal.make.ar_post_process + AR_POST_PROCESS + UnquotedString + none + none + makefile_variable + Command executed after archiver execution. + none + false + none + + + hal.make.as + AS + UnquotedString + nios2-elf-gcc + nios2-elf-gcc + makefile_variable + Assembler command. Note that CC is used for .S files. + none + false + none + + + hal.make.build_post_process + BUILD_POST_PROCESS + UnquotedString + none + none + makefile_variable + Command executed after BSP built. + none + false + none + + + hal.make.bsp_cflags_debug + BSP_CFLAGS_DEBUG + UnquotedString + none + -g + makefile_variable + C/C++ compiler debug level. '-g' provides the default set of debug symbols typically required to debug a typical application. Omitting '-g' removes debug symbols from the ELF. This setting defines the value of BSP_CFLAGS_DEBUG in Makefile. + none + false + common + + + hal.make.ar + AR + UnquotedString + nios2-elf-ar + nios2-elf-ar + makefile_variable + Archiver command. Creates library files. + none + false + none + + + hal.make.rm + RM + UnquotedString + rm -f + rm -f + makefile_variable + Command used to remove files during 'clean' target. + none + false + none + + + hal.make.cxx_pre_process + CXX_PRE_PROCESS + UnquotedString + none + none + makefile_variable + Command executed before each C++ file is compiled. + none + false + none + + + hal.make.bsp_cflags_warnings + BSP_CFLAGS_WARNINGS + UnquotedString + -Wall + -Wall + makefile_variable + C/C++ compiler warning level. "-Wall" is commonly used.This setting defines the value of BSP_CFLAGS_WARNINGS in Makefile. + none + false + none + + + hal.make.bsp_arflags + BSP_ARFLAGS + UnquotedString + -src + -src + makefile_variable + Custom flags only passed to the archiver. This content of this variable is directly passed to the archiver rather than the more standard "ARFLAGS". The reason for this is that GNU Make assumes some default content in ARFLAGS. This setting defines the value of BSP_ARFLAGS in Makefile. + none + false + none + + + hal.make.bsp_cflags_optimization + BSP_CFLAGS_OPTIMIZATION + UnquotedString + -Os + -O0 + makefile_variable + C/C++ compiler optimization level. "-O0" = no optimization,"-O2" = "normal" optimization, etc. "-O0" is recommended for code that you want to debug since compiler optimization can remove variables and produce non-sequential execution of code while debugging. This setting defines the value of BSP_CFLAGS_OPTIMIZATION in Makefile. + none + false + common + + + hal.make.as_post_process + AS_POST_PROCESS + UnquotedString + none + none + makefile_variable + Command executed after each assembly file is compiled. + none + false + none + + + hal.make.cc_pre_process + CC_PRE_PROCESS + UnquotedString + none + none + makefile_variable + Command executed before each .c/.S file is compiled. + none + false + none + + + hal.make.bsp_asflags + BSP_ASFLAGS + UnquotedString + -Wa,-gdwarf2 + -Wa,-gdwarf2 + makefile_variable + Custom flags only passed to the assembler. This setting defines the value of BSP_ASFLAGS in Makefile. + none + false + none + + + hal.make.as_pre_process + AS_PRE_PROCESS + UnquotedString + none + none + makefile_variable + Command executed before each assembly file is compiled. + none + false + none + + + hal.make.bsp_cflags_undefined_symbols + BSP_CFLAGS_UNDEFINED_SYMBOLS + UnquotedString + none + none + makefile_variable + Preprocessor macros to undefine. Undefined macros are similar to defined macros, but replicate the "#undef" directive in source code. To undefine the macro FOO use the syntax "-u FOO" in this setting. This is equivalent to "#undef FOO" in a source file. Note: the syntax differs from macro definition (there is a space, i.e. "-u FOO" versus "-DFOO"). Macros defined with this setting are applied to all .S, .c, and C++ files in the BSP. This setting defines the value of BSP_CFLAGS_UNDEFINED_SYMBOLS in the BSP Makefile. + none + false + none + + + hal.make.cc_post_process + CC_POST_PROCESS + UnquotedString + none + none + makefile_variable + Command executed after each .c/.S file is compiled. + none + false + none + + + hal.make.cxx_post_process + CXX_POST_PROCESS + UnquotedString + none + none + makefile_variable + Command executed before each C++ file is compiled. + none + false + none + + + hal.make.cc + CC + UnquotedString + nios2-elf-gcc -xc + nios2-elf-gcc -xc + makefile_variable + C compiler command. + none + false + none + + + hal.make.bsp_cxx_flags + BSP_CXXFLAGS + UnquotedString + none + none + makefile_variable + Custom flags only passed to the C++ compiler. This setting defines the value of BSP_CXXFLAGS in Makefile. + none + false + none + + + hal.make.bsp_inc_dirs + BSP_INC_DIRS + UnquotedString + none + none + makefile_variable + Space separated list of extra include directories to scan for header files. Directories are relative to the top-level BSP directory. The -I prefix's added by the makefile so don't add it here. This setting defines the value of BSP_INC_DIRS in Makefile. + none + false + none + + + hal.make.cxx + CXX + UnquotedString + nios2-elf-gcc -xc++ + nios2-elf-gcc -xc++ + makefile_variable + C++ compiler command. + none + false + none + + + hal.make.bsp_cflags_user_flags + BSP_CFLAGS_USER_FLAGS + UnquotedString + none + none + makefile_variable + Custom flags passed to the compiler when compiling C, C++, and .S files. This setting defines the value of BSP_CFLAGS_USER_FLAGS in Makefile. + none + false + none + + + hal.make.ignore_system_derived.sopc_system_id + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query SOPC system for system ID. If true ignores export of 'SOPC_SYSID_FLAG += --id=<sysid>' and 'ELF_PATCH_FLAG += --id=<sysid>' to public.mk. + none + false + none + + + hal.make.ignore_system_derived.sopc_system_timestamp + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query SOPC system for system timestamp. If true ignores export of 'SOPC_SYSID_FLAG += --timestamp=<timestamp>' and 'ELF_PATCH_FLAG += --timestamp=<timestamp>' to public.mk. + none + false + none + + + hal.make.ignore_system_derived.sopc_system_base_address + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query SOPC system for system ID base address. If true ignores export of 'SOPC_SYSID_FLAG += --sidp=<address>' and 'ELF_PATCH_FLAG += --sidp=<address>' to public.mk. + none + false + none + + + hal.make.ignore_system_derived.sopc_simulation_enabled + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system has simulation enabled. If true ignores export of 'ELF_PATCH_FLAG += --simulation_enabled' to public.mk. + none + false + none + + + hal.make.ignore_system_derived.fpu_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system has FPU present. If true ignores export of 'ALT_CFLAGS += -mhard-float' to public.mk if FPU is found in the system. If true ignores export of 'ALT_CFLAGS += -mhard-soft' if FPU is not found in the system. + none + false + none + + + hal.make.ignore_system_derived.cdx_present + none + Boolean + 0 + 0 + public_mk_define + If true, prevents GCC from using CDX instructions. If false, GCC uses CDX instructions if present in the CPU. + none + false + none + + + hal.make.ignore_system_derived.bmx_present + none + Boolean + 0 + 0 + public_mk_define + If true, prevents GCC from using BMX instructions. If false, GCC uses BMX instructions if present in the CPU. + none + false + none + + + hal.make.ignore_system_derived.hardware_multiplier_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system has multiplier present. If true ignores export of 'ALT_CFLAGS += -mno-hw-mul' to public.mk if no multiplier is found in the system. If true ignores export of 'ALT_CFLAGS += -mhw-mul' if multiplier is found in the system. + none + false + none + + + hal.make.ignore_system_derived.hardware_mulx_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system has hardware mulx present. If true ignores export of 'ALT_CFLAGS += -mno-hw-mulx' to public.mk if no mulx is found in the system. If true ignores export of 'ALT_CFLAGS += -mhw-mulx' if mulx is found in the system. + none + false + none + + + hal.make.ignore_system_derived.hardware_divide_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system has hardware divide present. If true ignores export of 'ALT_CFLAGS += -mno-hw-div' to public.mk if no division is found in system. If true ignores export of 'ALT_CFLAGS += -mhw-div' if division is found in the system. + none + false + none + + + hal.make.ignore_system_derived.debug_core_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system has a debug core present. If true ignores export of 'CPU_HAS_DEBUG_CORE = 1' to public.mk if a debug core is found in the system. If true ignores export of 'CPU_HAS_DEBUG_CORE = 0' if no debug core is found in the system. + none + false + none + + + hal.make.ignore_system_derived.big_endian + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system is big endian. If true ignores export of 'ALT_CFLAGS += -meb' to public.mk if big endian system. + none + false + none + + + hal.make.ignore_system_derived.hardware_fp_cust_inst_divider_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system floating point custom instruction with a divider is present. If true ignores export of 'ALT_CFLAGS += -mcustom-fpu-cfg=60-2' and 'ALT_LDFLAGS += -mcustom-fpu-cfg=60-2' to public.mk if the custom instruction is found in the system. + none + false + none + + + hal.make.ignore_system_derived.hardware_fp_cust_inst_no_divider_present + none + Boolean + 0 + 0 + public_mk_define + Enable BSP generation to query if SOPC system floating point custom instruction without a divider is present. If true ignores export of 'ALT_CFLAGS += -mcustom-fpu-cfg=60-1' and 'ALT_LDFLAGS += -mcustom-fpu-cfg=60-1' to public.mk if the custom instruction is found in the system. + none + false + none + + + hal.enable_exit + ALT_NO_EXIT + Boolean + 0 + 1 + public_mk_define + Add exit() support. This option increases code footprint if your "main()" routine does "return" or call "exit()". If false, adds -DALT_NO_EXIT to ALT_CPPFLAGS in public.mk, and reduces footprint + none + false + none + + + hal.enable_small_c_library + none + Boolean + 1 + 0 + public_mk_define + Causes the small newlib (C library) to be used. This reduces code and data footprint at the expense of reduced functionality. Several newlib features are removed such as floating-point support in printf(), stdin input routines, and buffered I/O. The small C library is not compatible with Micrium MicroC/OS-II. If true, adds -msmallc to ALT_LDFLAGS in public.mk. + none + false + common + + + hal.enable_clean_exit + ALT_NO_CLEAN_EXIT + Boolean + 0 + 1 + public_mk_define + When your application exits, close file descriptors, call C++ destructors, etc. Code footprint can be reduced by disabling clean exit. If disabled, adds -DALT_NO_CLEAN_EXIT to ALT_CPPFLAGS -D'exit(a)=_exit(a)' in public.mk. + none + false + none + + + hal.enable_runtime_stack_checking + ALT_STACK_CHECK + Boolean + 0 + 0 + public_mk_define + Turns on HAL runtime stack checking feature. Enabling this setting causes additional code to be placed into each subroutine call to generate an exception if a stack collision occurs with the heap or statically allocated data. If true, adds -DALT_STACK_CHECK and -fstack-limit-register=et to ALT_CPPFLAGS in public.mk. + none + false + none + + + hal.enable_gprof + ALT_PROVIDE_GMON + Boolean + 0 + 0 + public_mk_define + Causes code to be compiled with gprof profiling enabled and the application ELF to be linked with the GPROF library. If true, adds -DALT_PROVIDE_GMON to ALT_CPPFLAGS and -pg to ALT_CFLAGS in public.mk. + none + false + common + + + hal.enable_c_plus_plus + ALT_NO_C_PLUS_PLUS + Boolean + 0 + 1 + public_mk_define + Enable support for a subset of the C++ language. This option increases code footprint by adding support for C++ constructors. Certain features, such as multiple inheritance and exceptions are not supported. If false, adds -DALT_NO_C_PLUS_PLUS to ALT_CPPFLAGS in public.mk, and reduces code footprint. + none + false + none + + + hal.enable_reduced_device_drivers + ALT_USE_SMALL_DRIVERS + Boolean + 1 + 0 + public_mk_define + Certain drivers are compiled with reduced functionality to reduce code footprint. Not all drivers observe this setting. The altera_avalon_uart and altera_avalon_jtag_uart drivers switch from interrupt-driven to polled operation. CAUTION: Several device drivers are disabled entirely. These include the altera_avalon_cfi_flash, altera_avalon_epcs_flash_controller, and altera_avalon_lcd_16207 drivers. This can result in certain API (HAL flash access routines) to fail. You can define a symbol provided by each driver to prevent it from being removed. If true, adds -DALT_USE_SMALL_DRIVERS to ALT_CPPFLAGS in public.mk. + none + false + common + + + hal.enable_lightweight_device_driver_api + ALT_USE_DIRECT_DRIVERS + Boolean + 0 + 0 + public_mk_define + Enables lightweight device driver API. This reduces code and data footprint by removing the HAL layer that maps device names (e.g. /dev/uart0) to file descriptors. Instead, driver routines are called directly. The open(), close(), and lseek() routines will always fail if called. The read(), write(), fstat(), ioctl(), and isatty() routines only work for the stdio devices. If true, adds -DALT_USE_DIRECT_DRIVERS to ALT_CPPFLAGS in public.mk. + The Altera Host and read-only ZIP file systems can't be used if hal.enable_lightweight_device_driver_api is true. + false + none + + + hal.enable_mul_div_emulation + ALT_NO_INSTRUCTION_EMULATION + Boolean + 0 + 0 + public_mk_define + Adds code to emulate multiply and divide instructions in case they are executed but aren't present in the CPU. Normally this isn't required because the compiler won't use multiply and divide instructions that aren't present in the CPU. If false, adds -DALT_NO_INSTRUCTION_EMULATION to ALT_CPPFLAGS in public.mk. + none + false + none + + + hal.enable_sim_optimize + ALT_SIM_OPTIMIZE + Boolean + 0 + 0 + public_mk_define + The BSP is compiled with optimizations to speedup HDL simulation such as initializing the cache, clearing the .bss section, and skipping long delay loops. If true, adds -DALT_SIM_OPTIMIZE to ALT_CPPFLAGS in public.mk. + When this setting is true, the BSP shouldn't be used to build applications that are expected to run real hardware. + false + common + + + hal.enable_sopc_sysid_check + none + Boolean + 1 + 1 + public_mk_define + Enable SOPC Builder System ID. If a System ID SOPC Builder component is connected to the CPU associated with this BSP, it will be enabled in the creation of command-line arguments to download an ELF to the target. Otherwise, system ID and timestamp values are left out of public.mk for application Makefile "download-elf" target definition. With the system ID check disabled, the Nios II EDS tools will not automatically ensure that the application .elf file (and BSP it is linked against) corresponds to the hardware design on the target. If false, adds --accept-bad-sysid to SOPC_SYSID_FLAG in public.mk. + none + false + none + + + hal.custom_newlib_flags + CUSTOM_NEWLIB_FLAGS + UnquotedString + none + none + public_mk_define + Build a custom version of newlib with the specified space-separated compiler flags. + The custom newlib build will be placed in the <bsp root>/newlib directory, and will be used only for applications that utilize this BSP. + false + none + + + hal.log_flags + ALT_LOG_FLAGS + DecimalNumber + 0 + 0 + public_mk_define + The value is assigned to ALT_LOG_FLAGS in the generated public.mk. See hal.log_port setting description. Values can be -1 through 3. + hal.log_port must be set for this to be used. + false + none + + + altera_avalon_jtag_uart_driver.enable_small_driver + ALTERA_AVALON_JTAG_UART_SMALL + BooleanDefineOnly + false + false + public_mk_define + Small-footprint (polled mode) driver + none + false + + + + altera_avalon_jtag_uart_driver.enable_jtag_uart_ignore_fifo_full_error + ALTERA_AVALON_JTAG_UART_IGNORE_FIFO_FULL_ERROR + BooleanDefineOnly + true + false + public_mk_define + Enable JTAG UART driver to recover when host is inactive causing buffer to full without returning error. Printf will not fail with this recovery. + none + false + + + + epcq_controller_0_avl_mem + 0x00000000 - 0x007FFFFF + 8388608 + flash, memory, non-volatile + + + onchip_memory2_0 + 0x00810000 - 0x00818FFF + 36864 + memory + + + Altera_UP_SD_Card_Avalon_Interface_0 + 0x00821000 - 0x008213FF + 1024 + + + + epcq_controller_0_avl_csr + 0x00821400 - 0x0082141F + 32 + + + + i2c_opencores_0 + 0x00821420 - 0x0082143F + 32 + + + + pio_5 + 0x00821440 - 0x0082144F + 16 + + + + pio_4 + 0x00821450 - 0x0082145F + 16 + + + + pio_3 + 0x00821460 - 0x0082146F + 16 + + + + pio_2 + 0x00821470 - 0x0082147F + 16 + + + + pio_1 + 0x00821480 - 0x0082148F + 16 + + + + pio_0 + 0x00821490 - 0x0082149F + 16 + + + + jtag_uart_0 + 0x008214A0 - 0x008214A7 + 8 + printable + + + .text + onchip_memory2_0 + + + .rodata + onchip_memory2_0 + + + .rwdata + onchip_memory2_0 + + + .bss + onchip_memory2_0 + + + .heap + onchip_memory2_0 + + + .stack + onchip_memory2_0 + + \ No newline at end of file diff --git a/software/sys_controller_bsp/system.h b/software/sys_controller_bsp/system.h new file mode 100644 index 0000000..385398c --- /dev/null +++ b/software/sys_controller_bsp/system.h @@ -0,0 +1,484 @@ +/* + * system.h - SOPC Builder system and BSP software package information + * + * Machine generated for CPU 'nios2_qsys_0' in SOPC Builder design 'sys' + * SOPC Builder design path: ../../sys.sopcinfo + * + * Generated: Wed Dec 30 21:04:43 EET 2015 + */ + +/* + * DO NOT MODIFY THIS FILE + * + * Changing this file will have subtle consequences + * which will almost certainly lead to a nonfunctioning + * system. If you do modify this file, be aware that your + * changes will be overwritten and lost when this file + * is generated again. + * + * DO NOT MODIFY THIS FILE + */ + +/* + * License Agreement + * + * Copyright (c) 2008 + * Altera Corporation, San Jose, California, USA. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * This agreement shall be governed in all respects by the laws of the State + * of California and by the laws of the United States of America. + */ + +#ifndef __SYSTEM_H_ +#define __SYSTEM_H_ + +/* Include definitions from linker script generator */ +#include "linker.h" + + +/* + * Altera_UP_SD_Card_Avalon_Interface_0 configuration + * + */ + +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE 0x821000 +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_IRQ -1 +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_NAME "/dev/Altera_UP_SD_Card_Avalon_Interface_0" +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_SPAN 1024 +#define ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_TYPE "Altera_UP_SD_Card_Avalon_Interface_mod" +#define ALT_MODULE_CLASS_Altera_UP_SD_Card_Avalon_Interface_0 Altera_UP_SD_Card_Avalon_Interface_mod + + +/* + * CPU configuration + * + */ + +#define ALT_CPU_ARCHITECTURE "altera_nios2_gen2" +#define ALT_CPU_BIG_ENDIAN 0 +#define ALT_CPU_BREAK_ADDR 0x00820820 +#define ALT_CPU_CPU_ARCH_NIOS2_R1 +#define ALT_CPU_CPU_FREQ 27000000u +#define ALT_CPU_CPU_ID_SIZE 1 +#define ALT_CPU_CPU_ID_VALUE 0x00000000 +#define ALT_CPU_CPU_IMPLEMENTATION "tiny" +#define ALT_CPU_DATA_ADDR_WIDTH 0x18 +#define ALT_CPU_DCACHE_LINE_SIZE 0 +#define ALT_CPU_DCACHE_LINE_SIZE_LOG2 0 +#define ALT_CPU_DCACHE_SIZE 0 +#define ALT_CPU_EXCEPTION_ADDR 0x00810020 +#define ALT_CPU_FLASH_ACCELERATOR_LINES 0 +#define ALT_CPU_FLASH_ACCELERATOR_LINE_SIZE 0 +#define ALT_CPU_FLUSHDA_SUPPORTED +#define ALT_CPU_FREQ 27000000 +#define ALT_CPU_HARDWARE_DIVIDE_PRESENT 0 +#define ALT_CPU_HARDWARE_MULTIPLY_PRESENT 0 +#define ALT_CPU_HARDWARE_MULX_PRESENT 0 +#define ALT_CPU_HAS_DEBUG_CORE 1 +#define ALT_CPU_HAS_DEBUG_STUB +#define ALT_CPU_HAS_ILLEGAL_INSTRUCTION_EXCEPTION +#define ALT_CPU_HAS_JMPI_INSTRUCTION +#define ALT_CPU_ICACHE_LINE_SIZE 0 +#define ALT_CPU_ICACHE_LINE_SIZE_LOG2 0 +#define ALT_CPU_ICACHE_SIZE 0 +#define ALT_CPU_INST_ADDR_WIDTH 0x18 +#define ALT_CPU_NAME "nios2_qsys_0" +#define ALT_CPU_OCI_VERSION 1 +#define ALT_CPU_RESET_ADDR 0x00810000 + + +/* + * CPU configuration (with legacy prefix - don't use these anymore) + * + */ + +#define NIOS2_BIG_ENDIAN 0 +#define NIOS2_BREAK_ADDR 0x00820820 +#define NIOS2_CPU_ARCH_NIOS2_R1 +#define NIOS2_CPU_FREQ 27000000u +#define NIOS2_CPU_ID_SIZE 1 +#define NIOS2_CPU_ID_VALUE 0x00000000 +#define NIOS2_CPU_IMPLEMENTATION "tiny" +#define NIOS2_DATA_ADDR_WIDTH 0x18 +#define NIOS2_DCACHE_LINE_SIZE 0 +#define NIOS2_DCACHE_LINE_SIZE_LOG2 0 +#define NIOS2_DCACHE_SIZE 0 +#define NIOS2_EXCEPTION_ADDR 0x00810020 +#define NIOS2_FLASH_ACCELERATOR_LINES 0 +#define NIOS2_FLASH_ACCELERATOR_LINE_SIZE 0 +#define NIOS2_FLUSHDA_SUPPORTED +#define NIOS2_HARDWARE_DIVIDE_PRESENT 0 +#define NIOS2_HARDWARE_MULTIPLY_PRESENT 0 +#define NIOS2_HARDWARE_MULX_PRESENT 0 +#define NIOS2_HAS_DEBUG_CORE 1 +#define NIOS2_HAS_DEBUG_STUB +#define NIOS2_HAS_ILLEGAL_INSTRUCTION_EXCEPTION +#define NIOS2_HAS_JMPI_INSTRUCTION +#define NIOS2_ICACHE_LINE_SIZE 0 +#define NIOS2_ICACHE_LINE_SIZE_LOG2 0 +#define NIOS2_ICACHE_SIZE 0 +#define NIOS2_INST_ADDR_WIDTH 0x18 +#define NIOS2_OCI_VERSION 1 +#define NIOS2_RESET_ADDR 0x00810000 + + +/* + * Custom instruction macros + * + */ + +#define ALT_CI_NIOS2_HW_CRC32_0(n,A) __builtin_custom_ini(ALT_CI_NIOS2_HW_CRC32_0_N+(n&ALT_CI_NIOS2_HW_CRC32_0_N_MASK),(A)) +#define ALT_CI_NIOS2_HW_CRC32_0_N 0x0 +#define ALT_CI_NIOS2_HW_CRC32_0_N_MASK ((1<<3)-1) +#define ALT_CI_NIOS_CUSTOM_INSTR_BITSWAP_0(A) __builtin_custom_ini(ALT_CI_NIOS_CUSTOM_INSTR_BITSWAP_0_N,(A)) +#define ALT_CI_NIOS_CUSTOM_INSTR_BITSWAP_0_N 0x9 +#define ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(A) __builtin_custom_ini(ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0_N,(A)) +#define ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0_N 0x8 + + +/* + * Define for each module class mastered by the CPU + * + */ + +#define __ALTERA_AVALON_JTAG_UART +#define __ALTERA_AVALON_ONCHIP_MEMORY2 +#define __ALTERA_AVALON_PIO +#define __ALTERA_EPCQ_CONTROLLER_MOD +#define __ALTERA_NIOS2_GEN2 +#define __ALTERA_NIOS_CUSTOM_INSTR_BITSWAP +#define __ALTERA_NIOS_CUSTOM_INSTR_ENDIANCONVERTER +#define __ALTERA_UP_SD_CARD_AVALON_INTERFACE_MOD +#define __I2C_OPENCORES +#define __NIOS2_HW_CRC32 + + +/* + * System configuration + * + */ + +#define ALT_DEVICE_FAMILY "Cyclone IV E" +#define ALT_ENHANCED_INTERRUPT_API_PRESENT +#define ALT_IRQ_BASE NULL +#define ALT_LOG_PORT "/dev/null" +#define ALT_LOG_PORT_BASE 0x0 +#define ALT_LOG_PORT_DEV null +#define ALT_LOG_PORT_TYPE "" +#define ALT_NUM_EXTERNAL_INTERRUPT_CONTROLLERS 0 +#define ALT_NUM_INTERNAL_INTERRUPT_CONTROLLERS 1 +#define ALT_NUM_INTERRUPT_CONTROLLERS 1 +#define ALT_STDERR "/dev/jtag_uart_0" +#define ALT_STDERR_BASE 0x8214a0 +#define ALT_STDERR_DEV jtag_uart_0 +#define ALT_STDERR_IS_JTAG_UART +#define ALT_STDERR_PRESENT +#define ALT_STDERR_TYPE "altera_avalon_jtag_uart" +#define ALT_STDIN "/dev/jtag_uart_0" +#define ALT_STDIN_BASE 0x8214a0 +#define ALT_STDIN_DEV jtag_uart_0 +#define ALT_STDIN_IS_JTAG_UART +#define ALT_STDIN_PRESENT +#define ALT_STDIN_TYPE "altera_avalon_jtag_uart" +#define ALT_STDOUT "/dev/jtag_uart_0" +#define ALT_STDOUT_BASE 0x8214a0 +#define ALT_STDOUT_DEV jtag_uart_0 +#define ALT_STDOUT_IS_JTAG_UART +#define ALT_STDOUT_PRESENT +#define ALT_STDOUT_TYPE "altera_avalon_jtag_uart" +#define ALT_SYSTEM_NAME "sys" + + +/* + * epcq_controller_0_avl_csr configuration + * + */ + +#define ALT_MODULE_CLASS_epcq_controller_0_avl_csr altera_epcq_controller_mod +#define EPCQ_CONTROLLER_0_AVL_CSR_BASE 0x821400 +#define EPCQ_CONTROLLER_0_AVL_CSR_FLASH_TYPE "EPCS64" +#define EPCQ_CONTROLLER_0_AVL_CSR_IRQ 1 +#define EPCQ_CONTROLLER_0_AVL_CSR_IRQ_INTERRUPT_CONTROLLER_ID 0 +#define EPCQ_CONTROLLER_0_AVL_CSR_IS_EPCS 1 +#define EPCQ_CONTROLLER_0_AVL_CSR_NAME "/dev/epcq_controller_0_avl_csr" +#define EPCQ_CONTROLLER_0_AVL_CSR_NUMBER_OF_SECTORS 128 +#define EPCQ_CONTROLLER_0_AVL_CSR_PAGE_SIZE 256 +#define EPCQ_CONTROLLER_0_AVL_CSR_SECTOR_SIZE 65536 +#define EPCQ_CONTROLLER_0_AVL_CSR_SPAN 32 +#define EPCQ_CONTROLLER_0_AVL_CSR_SUBSECTOR_SIZE 4096 +#define EPCQ_CONTROLLER_0_AVL_CSR_TYPE "altera_epcq_controller_mod" + + +/* + * epcq_controller_0_avl_mem configuration + * + */ + +#define ALT_MODULE_CLASS_epcq_controller_0_avl_mem altera_epcq_controller_mod +#define EPCQ_CONTROLLER_0_AVL_MEM_BASE 0x0 +#define EPCQ_CONTROLLER_0_AVL_MEM_FLASH_TYPE "EPCS64" +#define EPCQ_CONTROLLER_0_AVL_MEM_IRQ -1 +#define EPCQ_CONTROLLER_0_AVL_MEM_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define EPCQ_CONTROLLER_0_AVL_MEM_IS_EPCS 1 +#define EPCQ_CONTROLLER_0_AVL_MEM_NAME "/dev/epcq_controller_0_avl_mem" +#define EPCQ_CONTROLLER_0_AVL_MEM_NUMBER_OF_SECTORS 128 +#define EPCQ_CONTROLLER_0_AVL_MEM_PAGE_SIZE 256 +#define EPCQ_CONTROLLER_0_AVL_MEM_SECTOR_SIZE 65536 +#define EPCQ_CONTROLLER_0_AVL_MEM_SPAN 8388608 +#define EPCQ_CONTROLLER_0_AVL_MEM_SUBSECTOR_SIZE 4096 +#define EPCQ_CONTROLLER_0_AVL_MEM_TYPE "altera_epcq_controller_mod" + + +/* + * hal configuration + * + */ + +#define ALT_MAX_FD 32 +#define ALT_SYS_CLK none +#define ALT_TIMESTAMP_CLK none + + +/* + * i2c_opencores_0 configuration + * + */ + +#define ALT_MODULE_CLASS_i2c_opencores_0 i2c_opencores +#define I2C_OPENCORES_0_BASE 0x821420 +#define I2C_OPENCORES_0_IRQ 0 +#define I2C_OPENCORES_0_IRQ_INTERRUPT_CONTROLLER_ID 0 +#define I2C_OPENCORES_0_NAME "/dev/i2c_opencores_0" +#define I2C_OPENCORES_0_SPAN 32 +#define I2C_OPENCORES_0_TYPE "i2c_opencores" + + +/* + * jtag_uart_0 configuration + * + */ + +#define ALT_MODULE_CLASS_jtag_uart_0 altera_avalon_jtag_uart +#define JTAG_UART_0_BASE 0x8214a0 +#define JTAG_UART_0_IRQ 2 +#define JTAG_UART_0_IRQ_INTERRUPT_CONTROLLER_ID 0 +#define JTAG_UART_0_NAME "/dev/jtag_uart_0" +#define JTAG_UART_0_READ_DEPTH 64 +#define JTAG_UART_0_READ_THRESHOLD 8 +#define JTAG_UART_0_SPAN 8 +#define JTAG_UART_0_TYPE "altera_avalon_jtag_uart" +#define JTAG_UART_0_WRITE_DEPTH 64 +#define JTAG_UART_0_WRITE_THRESHOLD 8 + + +/* + * onchip_memory2_0 configuration + * + */ + +#define ALT_MODULE_CLASS_onchip_memory2_0 altera_avalon_onchip_memory2 +#define ONCHIP_MEMORY2_0_ALLOW_IN_SYSTEM_MEMORY_CONTENT_EDITOR 0 +#define ONCHIP_MEMORY2_0_ALLOW_MRAM_SIM_CONTENTS_ONLY_FILE 0 +#define ONCHIP_MEMORY2_0_BASE 0x810000 +#define ONCHIP_MEMORY2_0_CONTENTS_INFO "" +#define ONCHIP_MEMORY2_0_DUAL_PORT 0 +#define ONCHIP_MEMORY2_0_GUI_RAM_BLOCK_TYPE "AUTO" +#define ONCHIP_MEMORY2_0_INIT_CONTENTS_FILE "sys_onchip_memory2_0" +#define ONCHIP_MEMORY2_0_INIT_MEM_CONTENT 1 +#define ONCHIP_MEMORY2_0_INSTANCE_ID "NONE" +#define ONCHIP_MEMORY2_0_IRQ -1 +#define ONCHIP_MEMORY2_0_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define ONCHIP_MEMORY2_0_NAME "/dev/onchip_memory2_0" +#define ONCHIP_MEMORY2_0_NON_DEFAULT_INIT_FILE_ENABLED 0 +#define ONCHIP_MEMORY2_0_RAM_BLOCK_TYPE "AUTO" +#define ONCHIP_MEMORY2_0_READ_DURING_WRITE_MODE "DONT_CARE" +#define ONCHIP_MEMORY2_0_SINGLE_CLOCK_OP 0 +#define ONCHIP_MEMORY2_0_SIZE_MULTIPLE 1 +#define ONCHIP_MEMORY2_0_SIZE_VALUE 36864 +#define ONCHIP_MEMORY2_0_SPAN 36864 +#define ONCHIP_MEMORY2_0_TYPE "altera_avalon_onchip_memory2" +#define ONCHIP_MEMORY2_0_WRITABLE 1 + + +/* + * pio_0 configuration + * + */ + +#define ALT_MODULE_CLASS_pio_0 altera_avalon_pio +#define PIO_0_BASE 0x821490 +#define PIO_0_BIT_CLEARING_EDGE_REGISTER 0 +#define PIO_0_BIT_MODIFYING_OUTPUT_REGISTER 0 +#define PIO_0_CAPTURE 0 +#define PIO_0_DATA_WIDTH 8 +#define PIO_0_DO_TEST_BENCH_WIRING 0 +#define PIO_0_DRIVEN_SIM_VALUE 0 +#define PIO_0_EDGE_TYPE "NONE" +#define PIO_0_FREQ 27000000 +#define PIO_0_HAS_IN 0 +#define PIO_0_HAS_OUT 1 +#define PIO_0_HAS_TRI 0 +#define PIO_0_IRQ -1 +#define PIO_0_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define PIO_0_IRQ_TYPE "NONE" +#define PIO_0_NAME "/dev/pio_0" +#define PIO_0_RESET_VALUE 0 +#define PIO_0_SPAN 16 +#define PIO_0_TYPE "altera_avalon_pio" + + +/* + * pio_1 configuration + * + */ + +#define ALT_MODULE_CLASS_pio_1 altera_avalon_pio +#define PIO_1_BASE 0x821480 +#define PIO_1_BIT_CLEARING_EDGE_REGISTER 0 +#define PIO_1_BIT_MODIFYING_OUTPUT_REGISTER 0 +#define PIO_1_CAPTURE 0 +#define PIO_1_DATA_WIDTH 32 +#define PIO_1_DO_TEST_BENCH_WIRING 0 +#define PIO_1_DRIVEN_SIM_VALUE 0 +#define PIO_1_EDGE_TYPE "NONE" +#define PIO_1_FREQ 27000000 +#define PIO_1_HAS_IN 1 +#define PIO_1_HAS_OUT 0 +#define PIO_1_HAS_TRI 0 +#define PIO_1_IRQ -1 +#define PIO_1_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define PIO_1_IRQ_TYPE "NONE" +#define PIO_1_NAME "/dev/pio_1" +#define PIO_1_RESET_VALUE 0 +#define PIO_1_SPAN 16 +#define PIO_1_TYPE "altera_avalon_pio" + + +/* + * pio_2 configuration + * + */ + +#define ALT_MODULE_CLASS_pio_2 altera_avalon_pio +#define PIO_2_BASE 0x821470 +#define PIO_2_BIT_CLEARING_EDGE_REGISTER 0 +#define PIO_2_BIT_MODIFYING_OUTPUT_REGISTER 0 +#define PIO_2_CAPTURE 0 +#define PIO_2_DATA_WIDTH 32 +#define PIO_2_DO_TEST_BENCH_WIRING 0 +#define PIO_2_DRIVEN_SIM_VALUE 0 +#define PIO_2_EDGE_TYPE "NONE" +#define PIO_2_FREQ 27000000 +#define PIO_2_HAS_IN 0 +#define PIO_2_HAS_OUT 1 +#define PIO_2_HAS_TRI 0 +#define PIO_2_IRQ -1 +#define PIO_2_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define PIO_2_IRQ_TYPE "NONE" +#define PIO_2_NAME "/dev/pio_2" +#define PIO_2_RESET_VALUE 0 +#define PIO_2_SPAN 16 +#define PIO_2_TYPE "altera_avalon_pio" + + +/* + * pio_3 configuration + * + */ + +#define ALT_MODULE_CLASS_pio_3 altera_avalon_pio +#define PIO_3_BASE 0x821460 +#define PIO_3_BIT_CLEARING_EDGE_REGISTER 0 +#define PIO_3_BIT_MODIFYING_OUTPUT_REGISTER 0 +#define PIO_3_CAPTURE 0 +#define PIO_3_DATA_WIDTH 32 +#define PIO_3_DO_TEST_BENCH_WIRING 0 +#define PIO_3_DRIVEN_SIM_VALUE 0 +#define PIO_3_EDGE_TYPE "NONE" +#define PIO_3_FREQ 27000000 +#define PIO_3_HAS_IN 0 +#define PIO_3_HAS_OUT 1 +#define PIO_3_HAS_TRI 0 +#define PIO_3_IRQ -1 +#define PIO_3_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define PIO_3_IRQ_TYPE "NONE" +#define PIO_3_NAME "/dev/pio_3" +#define PIO_3_RESET_VALUE 0 +#define PIO_3_SPAN 16 +#define PIO_3_TYPE "altera_avalon_pio" + + +/* + * pio_4 configuration + * + */ + +#define ALT_MODULE_CLASS_pio_4 altera_avalon_pio +#define PIO_4_BASE 0x821450 +#define PIO_4_BIT_CLEARING_EDGE_REGISTER 0 +#define PIO_4_BIT_MODIFYING_OUTPUT_REGISTER 0 +#define PIO_4_CAPTURE 0 +#define PIO_4_DATA_WIDTH 32 +#define PIO_4_DO_TEST_BENCH_WIRING 0 +#define PIO_4_DRIVEN_SIM_VALUE 0 +#define PIO_4_EDGE_TYPE "NONE" +#define PIO_4_FREQ 27000000 +#define PIO_4_HAS_IN 1 +#define PIO_4_HAS_OUT 0 +#define PIO_4_HAS_TRI 0 +#define PIO_4_IRQ -1 +#define PIO_4_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define PIO_4_IRQ_TYPE "NONE" +#define PIO_4_NAME "/dev/pio_4" +#define PIO_4_RESET_VALUE 0 +#define PIO_4_SPAN 16 +#define PIO_4_TYPE "altera_avalon_pio" + + +/* + * pio_5 configuration + * + */ + +#define ALT_MODULE_CLASS_pio_5 altera_avalon_pio +#define PIO_5_BASE 0x821440 +#define PIO_5_BIT_CLEARING_EDGE_REGISTER 0 +#define PIO_5_BIT_MODIFYING_OUTPUT_REGISTER 0 +#define PIO_5_CAPTURE 0 +#define PIO_5_DATA_WIDTH 8 +#define PIO_5_DO_TEST_BENCH_WIRING 0 +#define PIO_5_DRIVEN_SIM_VALUE 0 +#define PIO_5_EDGE_TYPE "NONE" +#define PIO_5_FREQ 27000000 +#define PIO_5_HAS_IN 0 +#define PIO_5_HAS_OUT 1 +#define PIO_5_HAS_TRI 0 +#define PIO_5_IRQ -1 +#define PIO_5_IRQ_INTERRUPT_CONTROLLER_ID -1 +#define PIO_5_IRQ_TYPE "NONE" +#define PIO_5_NAME "/dev/pio_5" +#define PIO_5_RESET_VALUE 0 +#define PIO_5_SPAN 16 +#define PIO_5_TYPE "altera_avalon_pio" + +#endif /* __SYSTEM_H_ */ diff --git a/sys.qsys b/sys.qsys new file mode 100644 index 0000000..349b161 --- /dev/null +++ b/sys.qsys @@ -0,0 +1,951 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ADDRESS_STALL 1 ADVANCED_INFO 0 ALLOWS_COMPILING_OTHER_FAMILY_IP 1 ANY_QFP 0 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 0 DSP_SHIFTER_BLOCK 0 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 1 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 ENABLE_PIN_PLANNER 0 ENGINEERING_SAMPLE 0 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FAMILY_LEVEL_INSTALLATION_ONLY 1 FASTEST 0 FINAL_TIMING_MODEL 0 FITTER_USE_FALLING_EDGE_DELAY 0 FPP_COMPLETELY_PLACES_AND_ROUTES_PERIPHERY 0 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 0 HARDCOPY 0 HAS_18_BIT_MULTS 0 HAS_ACE_SUPPORT 1 HAS_ACTIVE_PARALLEL_FLASH_SUPPORT 0 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 0 HAS_ADVANCED_IO_INVERTED_CORNER 0 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 0 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 0 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CDB_RE_NETWORK_PRESERVATION_SUPPORT 0 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 0 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DAP_JTAG_FROM_HPS 0 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 1 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 1 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 0 HAS_ERROR_DETECTION_SUPPORT 0 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_FUNCTIONAL_VERILOG_SIMULATION_SUPPORT 0 HAS_FUNCTIONAL_VHDL_SIMULATION_SUPPORT 0 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HARDCOPYII_SUPPORT 0 HAS_HC_READY_SUPPORT 0 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 0 HAS_IBISO_WRITER_SUPPORT 0 HAS_ICD_DATA_IP 0 HAS_IDB_SUPPORT 1 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 0 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_PLACEMENT_USING_GEOMETRY_RULE 0 HAS_IO_PLACEMENT_USING_PHYSIC_RULE 0 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NADDER_STYLE_FF 0 HAS_NADDER_STYLE_LCELL_COMB 0 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_NO_HARDBLOCK_PARTITION_SUPPORT 0 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PASSIVE_PARALLEL_SUPPORT 0 HAS_PHYSICAL_DESIGN_PLANNER_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 0 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_BINNING_LIMITS_DATA 0 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 0 HAS_PVA_SUPPORT 1 HAS_QUARTUS_HIERARCHICAL_DESIGN_SUPPORT 0 HAS_RAPID_RECOMPILE_SUPPORT 0 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_STRICT_PRESERVATION_SUPPORT 1 HAS_SYNTHESIS_ON_ATOMS 0 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TCL_FITTER_SUPPORT 0 HAS_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 0 HAS_U2B2_SUPPORT 0 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_USE_FITTER_INFO_SUPPORT 1 HAS_VCCPD_POWER_RAIL 0 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO2_WRITER_SUPPORT 0 HAS_XIBISO_WRITER_SUPPORT 1 IFP_USE_LEGACY_IO_CHECKER 0 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 INTERNAL_POF_SUPPORT_ENABLED 0 INTERNAL_USE_ONLY 0 ISSUE_MILITARY_TEMPERATURE_WARNING 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_FOR_INTERNAL_TESTING_ONLY 0 IS_HARDCOPY_FAMILY 0 IS_HBGA_PACKAGE 0 IS_HIGH_CURRENT_PART 0 IS_LOW_POWER_PART 0 IS_SDM_ONLY_PACKAGE 0 IS_SMI_PART 0 LOAD_BLK_TYPE_DATA_FROM_ATOM_WYS_INFO 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 0 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 0 MRAM_MEMORY 0 NOT_LISTED 0 NOT_MIGRATABLE 0 NO_FITTER_DELAY_CACHE_GENERATED 0 NO_PIN_OUT 0 NO_POF 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_ONLY 0 PROGRAMMER_SUPPORT 1 PVA_SUPPORTS_ONLY_SUBSET_OF_ATOMS 0 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 REQUIRE_QUARTUS_HIERARCHICAL_DESIGN 0 REQUIRE_SPECIAL_HANDLING_FOR_LOCAL_LABLINE 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RESTRICT_PARTIAL_RECONFIG 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SHOW_HIDDEN_FAMILY_IN_PROGRAMMER 0 STRICT_TIMING_DB_CHECKS 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 0 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 0 SUPPORTS_HIPI_RETIMING 0 SUPPORTS_MAC_CHAIN_OUT_ADDER 0 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 SUPPORTS_VID 0 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 0 TRANSCEIVER_6G_BLOCK 0 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ALTERA_LNSIM 0 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_NETWORK_ROUTING_POWER_CALCULATOR 0 USES_PART_INFO_FOR_DISPLAYING_CORE_VOLTAGE_VALUE 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_PVAFAM2 0 USES_SECOND_GENERATION_PART_INFO 0 USES_SECOND_GENERATION_POWER_ANALYZER 0 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USES_U2B2_TIMING_MODELS 0 USES_XML_FORMAT_FOR_EMIF_PIN_MAP_FILE 0 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 1 USE_RELAX_IO_ASSIGNMENT_RULES 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 0 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 0 USING_28NM_OR_OLDER_TIMING_METHODOLOGY 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + + + + + + + + + + + NO_INTERACTIVE_WINDOWS + + + + + + + + + + + + + + + + + + + + + + nios2_qsys_0.jtag_debug_module + + + + + + ]]> + + + + + + + ]]> + + + + + + + + + + + + + + + + + + + + + + ADDRESS_STALL 1 ADVANCED_INFO 0 ALLOWS_COMPILING_OTHER_FAMILY_IP 1 ANY_QFP 0 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 0 DSP_SHIFTER_BLOCK 0 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 1 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 ENABLE_PIN_PLANNER 0 ENGINEERING_SAMPLE 0 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FAMILY_LEVEL_INSTALLATION_ONLY 1 FASTEST 0 FINAL_TIMING_MODEL 0 FITTER_USE_FALLING_EDGE_DELAY 0 FPP_COMPLETELY_PLACES_AND_ROUTES_PERIPHERY 0 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 0 HARDCOPY 0 HAS_18_BIT_MULTS 0 HAS_ACE_SUPPORT 1 HAS_ACTIVE_PARALLEL_FLASH_SUPPORT 0 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 0 HAS_ADVANCED_IO_INVERTED_CORNER 0 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 0 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 0 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CDB_RE_NETWORK_PRESERVATION_SUPPORT 0 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 0 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DAP_JTAG_FROM_HPS 0 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 1 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 1 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 0 HAS_ERROR_DETECTION_SUPPORT 0 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_FUNCTIONAL_VERILOG_SIMULATION_SUPPORT 0 HAS_FUNCTIONAL_VHDL_SIMULATION_SUPPORT 0 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HARDCOPYII_SUPPORT 0 HAS_HC_READY_SUPPORT 0 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 0 HAS_IBISO_WRITER_SUPPORT 0 HAS_ICD_DATA_IP 0 HAS_IDB_SUPPORT 1 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 0 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_PLACEMENT_USING_GEOMETRY_RULE 0 HAS_IO_PLACEMENT_USING_PHYSIC_RULE 0 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NADDER_STYLE_FF 0 HAS_NADDER_STYLE_LCELL_COMB 0 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_NO_HARDBLOCK_PARTITION_SUPPORT 0 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PASSIVE_PARALLEL_SUPPORT 0 HAS_PHYSICAL_DESIGN_PLANNER_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 0 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_BINNING_LIMITS_DATA 0 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 0 HAS_PVA_SUPPORT 1 HAS_QUARTUS_HIERARCHICAL_DESIGN_SUPPORT 0 HAS_RAPID_RECOMPILE_SUPPORT 0 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_STRICT_PRESERVATION_SUPPORT 1 HAS_SYNTHESIS_ON_ATOMS 0 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TCL_FITTER_SUPPORT 0 HAS_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 0 HAS_U2B2_SUPPORT 0 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_USE_FITTER_INFO_SUPPORT 1 HAS_VCCPD_POWER_RAIL 0 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO2_WRITER_SUPPORT 0 HAS_XIBISO_WRITER_SUPPORT 1 IFP_USE_LEGACY_IO_CHECKER 0 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 INTERNAL_POF_SUPPORT_ENABLED 0 INTERNAL_USE_ONLY 0 ISSUE_MILITARY_TEMPERATURE_WARNING 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_FOR_INTERNAL_TESTING_ONLY 0 IS_HARDCOPY_FAMILY 0 IS_HBGA_PACKAGE 0 IS_HIGH_CURRENT_PART 0 IS_LOW_POWER_PART 0 IS_SDM_ONLY_PACKAGE 0 IS_SMI_PART 0 LOAD_BLK_TYPE_DATA_FROM_ATOM_WYS_INFO 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 0 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 0 MRAM_MEMORY 0 NOT_LISTED 0 NOT_MIGRATABLE 0 NO_FITTER_DELAY_CACHE_GENERATED 0 NO_PIN_OUT 0 NO_POF 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_ONLY 0 PROGRAMMER_SUPPORT 1 PVA_SUPPORTS_ONLY_SUBSET_OF_ATOMS 0 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 REQUIRE_QUARTUS_HIERARCHICAL_DESIGN 0 REQUIRE_SPECIAL_HANDLING_FOR_LOCAL_LABLINE 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RESTRICT_PARTIAL_RECONFIG 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SHOW_HIDDEN_FAMILY_IN_PROGRAMMER 0 STRICT_TIMING_DB_CHECKS 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 0 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 0 SUPPORTS_HIPI_RETIMING 0 SUPPORTS_MAC_CHAIN_OUT_ADDER 0 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 SUPPORTS_VID 0 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 0 TRANSCEIVER_6G_BLOCK 0 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ALTERA_LNSIM 0 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_NETWORK_ROUTING_POWER_CALCULATOR 0 USES_PART_INFO_FOR_DISPLAYING_CORE_VOLTAGE_VALUE 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_PVAFAM2 0 USES_SECOND_GENERATION_PART_INFO 0 USES_SECOND_GENERATION_POWER_ANALYZER 0 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USES_U2B2_TIMING_MODELS 0 USES_XML_FORMAT_FOR_EMIF_PIN_MAP_FILE 0 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 1 USE_RELAX_IO_ASSIGNMENT_RULES 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 0 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 0 USING_28NM_OR_OLDER_TIMING_METHODOLOGY 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $${FILENAME}_onchip_memory2_0 + + + + + ADDRESS_STALL 1 ADVANCED_INFO 0 ALLOWS_COMPILING_OTHER_FAMILY_IP 1 ANY_QFP 0 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 0 DSP_SHIFTER_BLOCK 0 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 1 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 ENABLE_PIN_PLANNER 0 ENGINEERING_SAMPLE 0 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FAMILY_LEVEL_INSTALLATION_ONLY 1 FASTEST 0 FINAL_TIMING_MODEL 0 FITTER_USE_FALLING_EDGE_DELAY 0 FPP_COMPLETELY_PLACES_AND_ROUTES_PERIPHERY 0 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 0 HARDCOPY 0 HAS_18_BIT_MULTS 0 HAS_ACE_SUPPORT 1 HAS_ACTIVE_PARALLEL_FLASH_SUPPORT 0 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 0 HAS_ADVANCED_IO_INVERTED_CORNER 0 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 0 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 0 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CDB_RE_NETWORK_PRESERVATION_SUPPORT 0 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 0 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DAP_JTAG_FROM_HPS 0 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 1 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 1 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 0 HAS_ERROR_DETECTION_SUPPORT 0 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_FUNCTIONAL_VERILOG_SIMULATION_SUPPORT 0 HAS_FUNCTIONAL_VHDL_SIMULATION_SUPPORT 0 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HARDCOPYII_SUPPORT 0 HAS_HC_READY_SUPPORT 0 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 0 HAS_IBISO_WRITER_SUPPORT 0 HAS_ICD_DATA_IP 0 HAS_IDB_SUPPORT 1 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 0 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_PLACEMENT_USING_GEOMETRY_RULE 0 HAS_IO_PLACEMENT_USING_PHYSIC_RULE 0 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NADDER_STYLE_FF 0 HAS_NADDER_STYLE_LCELL_COMB 0 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_NO_HARDBLOCK_PARTITION_SUPPORT 0 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PASSIVE_PARALLEL_SUPPORT 0 HAS_PHYSICAL_DESIGN_PLANNER_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 0 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_BINNING_LIMITS_DATA 0 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 0 HAS_PVA_SUPPORT 1 HAS_QUARTUS_HIERARCHICAL_DESIGN_SUPPORT 0 HAS_RAPID_RECOMPILE_SUPPORT 0 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_STRICT_PRESERVATION_SUPPORT 1 HAS_SYNTHESIS_ON_ATOMS 0 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TCL_FITTER_SUPPORT 0 HAS_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 0 HAS_U2B2_SUPPORT 0 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_USE_FITTER_INFO_SUPPORT 1 HAS_VCCPD_POWER_RAIL 0 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO2_WRITER_SUPPORT 0 HAS_XIBISO_WRITER_SUPPORT 1 IFP_USE_LEGACY_IO_CHECKER 0 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 INTERNAL_POF_SUPPORT_ENABLED 0 INTERNAL_USE_ONLY 0 ISSUE_MILITARY_TEMPERATURE_WARNING 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_FOR_INTERNAL_TESTING_ONLY 0 IS_HARDCOPY_FAMILY 0 IS_HBGA_PACKAGE 0 IS_HIGH_CURRENT_PART 0 IS_LOW_POWER_PART 0 IS_SDM_ONLY_PACKAGE 0 IS_SMI_PART 0 LOAD_BLK_TYPE_DATA_FROM_ATOM_WYS_INFO 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 0 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 0 MRAM_MEMORY 0 NOT_LISTED 0 NOT_MIGRATABLE 0 NO_FITTER_DELAY_CACHE_GENERATED 0 NO_PIN_OUT 0 NO_POF 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_ONLY 0 PROGRAMMER_SUPPORT 1 PVA_SUPPORTS_ONLY_SUBSET_OF_ATOMS 0 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 REQUIRE_QUARTUS_HIERARCHICAL_DESIGN 0 REQUIRE_SPECIAL_HANDLING_FOR_LOCAL_LABLINE 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RESTRICT_PARTIAL_RECONFIG 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SHOW_HIDDEN_FAMILY_IN_PROGRAMMER 0 STRICT_TIMING_DB_CHECKS 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 0 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 0 SUPPORTS_HIPI_RETIMING 0 SUPPORTS_MAC_CHAIN_OUT_ADDER 0 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 SUPPORTS_VID 0 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 0 TRANSCEIVER_6G_BLOCK 0 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ALTERA_LNSIM 0 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_NETWORK_ROUTING_POWER_CALCULATOR 0 USES_PART_INFO_FOR_DISPLAYING_CORE_VOLTAGE_VALUE 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_PVAFAM2 0 USES_SECOND_GENERATION_PART_INFO 0 USES_SECOND_GENERATION_POWER_ANALYZER 0 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USES_U2B2_TIMING_MODELS 0 USES_XML_FORMAT_FOR_EMIF_PIN_MAP_FILE 0 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 1 USE_RELAX_IO_ASSIGNMENT_RULES 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 0 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 0 USING_28NM_OR_OLDER_TIMING_METHODOLOGY 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nios_custom_instr_endianconverter_0 + + + + + nios_custom_instr_bitswap_0 + + + + + + + + + + + + + + + + + + + diff --git a/sys.sopcinfo b/sys.sopcinfo new file mode 100644 index 0000000..85e1176 --- /dev/null +++ b/sys.sopcinfo @@ -0,0 +1,14864 @@ + + + + + + + java.lang.Integer + 1453239707 + false + true + false + true + GENERATION_ID + + + java.lang.String + + false + true + false + true + UNIQUE_ID + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + java.lang.String + EP4CE15E22C8 + false + true + false + true + DEVICE + + + java.lang.String + 8 + false + true + false + true + DEVICE_SPEEDGRADE + + + java.lang.Long + -1 + false + true + false + true + CLOCK_RATE + clk + + + java.lang.Integer + -1 + false + true + false + true + CLOCK_DOMAIN + clk + + + java.lang.Integer + -1 + false + true + false + true + RESET_DOMAIN + clk + + + java.lang.String + Cyclone IV E + false + true + false + true + DEVICE_FAMILY + + + boolean + false + false + true + true + true + + + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + java.lang.Long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + java.lang.String + Cyclone IV E + false + true + false + true + DEVICE_FAMILY + + + boolean + false + false + true + true + true + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + DYNAMIC + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 1024 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + i_avalon_chip_select + Input + 1 + chipselect + + + i_avalon_address + Input + 8 + address + + + i_avalon_read + Input + 1 + read + + + i_avalon_write + Input + 1 + write + + + i_avalon_byteenable + Input + 4 + byteenable + + + i_avalon_writedata + Input + 32 + writedata + + + o_avalon_readdata + Output + 32 + readdata + + + o_avalon_waitrequest + Output + 1 + waitrequest + + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + i_clock + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + i_reset_n + Input + 1 + reset_n + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + b_SD_cmd + Bidir + 1 + export + + + b_SD_dat + Bidir + 1 + export + + + b_SD_dat3 + Bidir + 1 + export + + + o_SD_clock + Output + 1 + export + + + + + + + long + 27000000 + false + true + true + true + + + boolean + true + false + true + true + true + + + long + 0 + false + true + false + true + CLOCK_RATE + clk_in + + + com.altera.sopcmodel.reset.Reset$Edges + NONE + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + qsys.ui.export_name + clk + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + in_clk + Input + 1 + clk + + + + + + qsys.ui.export_name + reset + + + java.lang.String + + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + NONE + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + java.lang.String + clk_in + false + true + true + true + + + long + 27000000 + false + true + true + true + + + boolean + true + false + true + true + true + + + boolean + true + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clock + true + + clk_out + Output + 1 + clk + + + false + nios2_qsys_0 + clk + nios2_qsys_0.clk + + + false + jtag_uart_0 + clk + jtag_uart_0.clk + + + false + pio_0 + clk + pio_0.clk + + + false + pio_1 + clk + pio_1.clk + + + false + pio_2 + clk + pio_2.clk + + + false + pio_3 + clk + pio_3.clk + + + false + pio_4 + clk + pio_4.clk + + + false + Altera_UP_SD_Card_Avalon_Interface_0 + clk + Altera_UP_SD_Card_Avalon_Interface_0.clk + + + false + pio_5 + clk + pio_5.clk + + + false + onchip_memory2_0 + clk1 + onchip_memory2_0.clk1 + + + false + i2c_opencores_0 + clock + i2c_opencores_0.clock + + + false + epcq_controller_0 + clock_sink + epcq_controller_0.clock_sink + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + clk_in_reset + false + true + true + true + + + [Ljava.lang.String; + clk_in_reset + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + NONE + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + true + + reset_n_out + Output + 1 + reset_n + + + + + + + embeddedsw.CMacro.FLASH_TYPE + EPCS64 + + + embeddedsw.CMacro.IS_EPCS + 1 + + + embeddedsw.CMacro.NUMBER_OF_SECTORS + 128 + + + embeddedsw.CMacro.PAGE_SIZE + 256 + + + embeddedsw.CMacro.SECTOR_SIZE + 65536 + + + embeddedsw.CMacro.SUBSECTOR_SIZE + 4096 + + + embeddedsw.dts.compatible + altr,epcq-1.0 + + + embeddedsw.dts.group + epcq + + + embeddedsw.dts.name + epcq + + + embeddedsw.dts.vendor + altr + + + embeddedsw.memoryInfo.GENERATE_DAT_SYM + 0 + + + embeddedsw.memoryInfo.GENERATE_FLASH + 0 + + + embeddedsw.memoryInfo.GENERATE_HEX + 1 + + + embeddedsw.memoryInfo.HEX_INSTALL_DIR + QPF_DIR + + + embeddedsw.memoryInfo.IS_FLASH + 1 + + + embeddedsw.memoryInfo.MEM_INIT_DATA_WIDTH + 32 + + + embeddedsw.memoryInfo.USE_BYTE_ADDRESSING_FOR_HEX + 1 + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + int + 1 + true + true + false + true + + + int + 1 + true + true + false + true + + + int + 21 + true + true + false + true + + + int + 24 + true + true + false + true + + + int + 0 + true + true + false + true + + + java.lang.String + ADDRESS_STALL 1 ADVANCED_INFO 0 ALLOWS_COMPILING_OTHER_FAMILY_IP 1 ANY_QFP 0 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 0 DSP_SHIFTER_BLOCK 0 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 1 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 ENABLE_PIN_PLANNER 0 ENGINEERING_SAMPLE 0 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FAMILY_LEVEL_INSTALLATION_ONLY 1 FASTEST 0 FINAL_TIMING_MODEL 0 FITTER_USE_FALLING_EDGE_DELAY 0 FPP_COMPLETELY_PLACES_AND_ROUTES_PERIPHERY 0 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 0 HARDCOPY 0 HAS_18_BIT_MULTS 0 HAS_ACE_SUPPORT 1 HAS_ACTIVE_PARALLEL_FLASH_SUPPORT 0 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 0 HAS_ADVANCED_IO_INVERTED_CORNER 0 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 0 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 0 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CDB_RE_NETWORK_PRESERVATION_SUPPORT 0 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 0 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DAP_JTAG_FROM_HPS 0 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 1 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 1 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 0 HAS_ERROR_DETECTION_SUPPORT 0 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_FUNCTIONAL_VERILOG_SIMULATION_SUPPORT 0 HAS_FUNCTIONAL_VHDL_SIMULATION_SUPPORT 0 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HARDCOPYII_SUPPORT 0 HAS_HC_READY_SUPPORT 0 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 0 HAS_IBISO_WRITER_SUPPORT 0 HAS_ICD_DATA_IP 0 HAS_IDB_SUPPORT 1 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 0 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_PLACEMENT_USING_GEOMETRY_RULE 0 HAS_IO_PLACEMENT_USING_PHYSIC_RULE 0 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NADDER_STYLE_FF 0 HAS_NADDER_STYLE_LCELL_COMB 0 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_NO_HARDBLOCK_PARTITION_SUPPORT 0 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PASSIVE_PARALLEL_SUPPORT 0 HAS_PHYSICAL_DESIGN_PLANNER_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 0 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_BINNING_LIMITS_DATA 0 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 0 HAS_PVA_SUPPORT 1 HAS_QUARTUS_HIERARCHICAL_DESIGN_SUPPORT 0 HAS_RAPID_RECOMPILE_SUPPORT 0 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_STRICT_PRESERVATION_SUPPORT 1 HAS_SYNTHESIS_ON_ATOMS 0 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TCL_FITTER_SUPPORT 0 HAS_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 0 HAS_U2B2_SUPPORT 0 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_USE_FITTER_INFO_SUPPORT 1 HAS_VCCPD_POWER_RAIL 0 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO2_WRITER_SUPPORT 0 HAS_XIBISO_WRITER_SUPPORT 1 IFP_USE_LEGACY_IO_CHECKER 0 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 INTERNAL_POF_SUPPORT_ENABLED 0 INTERNAL_USE_ONLY 0 ISSUE_MILITARY_TEMPERATURE_WARNING 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_FOR_INTERNAL_TESTING_ONLY 0 IS_HARDCOPY_FAMILY 0 IS_HBGA_PACKAGE 0 IS_HIGH_CURRENT_PART 0 IS_LOW_POWER_PART 0 IS_SDM_ONLY_PACKAGE 0 IS_SMI_PART 0 LOAD_BLK_TYPE_DATA_FROM_ATOM_WYS_INFO 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 0 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 0 MRAM_MEMORY 0 NOT_LISTED 0 NOT_MIGRATABLE 0 NO_FITTER_DELAY_CACHE_GENERATED 0 NO_PIN_OUT 0 NO_POF 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_ONLY 0 PROGRAMMER_SUPPORT 1 PVA_SUPPORTS_ONLY_SUBSET_OF_ATOMS 0 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 REQUIRE_QUARTUS_HIERARCHICAL_DESIGN 0 REQUIRE_SPECIAL_HANDLING_FOR_LOCAL_LABLINE 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RESTRICT_PARTIAL_RECONFIG 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SHOW_HIDDEN_FAMILY_IN_PROGRAMMER 0 STRICT_TIMING_DB_CHECKS 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 0 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 0 SUPPORTS_HIPI_RETIMING 0 SUPPORTS_MAC_CHAIN_OUT_ADDER 0 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 SUPPORTS_VID 0 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 0 TRANSCEIVER_6G_BLOCK 0 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ALTERA_LNSIM 0 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_NETWORK_ROUTING_POWER_CALCULATOR 0 USES_PART_INFO_FOR_DISPLAYING_CORE_VOLTAGE_VALUE 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_PVAFAM2 0 USES_SECOND_GENERATION_PART_INFO 0 USES_SECOND_GENERATION_POWER_ANALYZER 0 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USES_U2B2_TIMING_MODELS 0 USES_XML_FORMAT_FOR_EMIF_PIN_MAP_FILE 0 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 1 USE_RELAX_IO_ASSIGNMENT_RULES 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 0 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 0 USING_28NM_OR_OLDER_TIMING_METHODOLOGY 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + false + true + false + true + DEVICE_FEATURES + + + int + 0 + false + true + false + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clock_sink + + + java.lang.String + EPCS64 + false + true + true + true + + + java.lang.String + STANDARD + false + false + true + true + + + int + 1 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clock_sink + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + DYNAMIC + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 32 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clock_sink + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 1 + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + avl_csr_read + Input + 1 + read + + + avl_csr_waitrequest + Output + 1 + waitrequest + + + avl_csr_write + Input + 1 + write + + + avl_csr_addr + Input + 3 + address + + + avl_csr_wrdata + Input + 32 + writedata + + + avl_csr_rddata + Output + 32 + readdata + + + avl_csr_rddata_valid + Output + 1 + readdatavalid + + + + + + embeddedsw.configuration.isFlash + 1 + + + embeddedsw.configuration.isMemoryDevice + 1 + + + embeddedsw.configuration.isNonVolatileStorage + 1 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + DYNAMIC + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 8388608 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clock_sink + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + true + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + true + false + true + true + true + + + int + 1 + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + avl_mem_write + Input + 1 + write + + + avl_mem_burstcount + Input + 7 + burstcount + + + avl_mem_waitrequest + Output + 1 + waitrequest + + + avl_mem_read + Input + 1 + read + + + avl_mem_addr + Input + 21 + address + + + avl_mem_wrdata + Input + 32 + writedata + + + avl_mem_rddata + Output + 32 + readdata + + + avl_mem_rddata_valid + Output + 1 + readdatavalid + + + avl_mem_byteenable + Input + 4 + byteenable + + + + + + com.altera.entityinterfaces.IConnectionPoint + epcq_controller_0.avl_csr + false + true + true + true + + + java.lang.String + clock_sink + false + true + false + true + + + java.lang.String + reset + false + true + false + true + + + java.lang.Integer + + false + true + true + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + true + true + + + com.altera.sopcmodel.interrupt.InterruptConnectionPoint$EIrqScheme + NONE + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + interrupt + false + + irq + Output + 1 + irq + + + + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clock + false + + wb_clk_i + Input + 1 + clk + + + + + + java.lang.String + clock + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + wb_rst_i + Input + 1 + reset + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + scl_pad_io + Bidir + 1 + export + + + sda_pad_io + Bidir + 1 + export + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 8 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clock + false + true + true + true + + + java.lang.String + clock_reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + wb_adr_i + Input + 3 + address + + + wb_dat_i + Input + 8 + writedata + + + wb_dat_o + Output + 8 + readdata + + + wb_we_i + Input + 1 + write + + + wb_stb_i + Input + 1 + chipselect + + + wb_ack_o + Output + 1 + waitrequest_n + + + + + + com.altera.entityinterfaces.IConnectionPoint + i2c_opencores_0.avalon_slave_0 + false + true + true + true + + + java.lang.String + clock + false + true + false + true + + + java.lang.String + clock_reset + false + true + false + true + + + java.lang.Integer + + false + true + true + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + true + true + + + com.altera.sopcmodel.interrupt.InterruptConnectionPoint$EIrqScheme + NONE + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + interrupt + false + + wb_inta_o + Output + 1 + irq + + + + + + + embeddedsw.CMacro.READ_DEPTH + 64 + + + embeddedsw.CMacro.READ_THRESHOLD + 8 + + + embeddedsw.CMacro.WRITE_DEPTH + 64 + + + embeddedsw.CMacro.WRITE_THRESHOLD + 8 + + + embeddedsw.dts.compatible + altr,juart-1.0 + + + embeddedsw.dts.group + serial + + + embeddedsw.dts.name + juart + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 64 + false + true + true + true + + + int + 8 + false + true + true + true + + + java.lang.String + + false + false + false + true + + + java.lang.String + NO_INTERACTIVE_WINDOWS + false + true + false + true + + + boolean + false + false + true + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + true + false + true + + + int + 64 + false + true + true + true + + + int + 8 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + java.lang.String + 2.0 + false + true + false + true + AVALON_SPEC + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + rst_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 1 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 2 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + true + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + av_chipselect + Input + 1 + chipselect + + + av_address + Input + 1 + address + + + av_read_n + Input + 1 + read_n + + + av_readdata + Output + 32 + readdata + + + av_write_n + Input + 1 + write_n + + + av_writedata + Input + 32 + writedata + + + av_waitrequest + Output + 1 + waitrequest + + + + + + com.altera.entityinterfaces.IConnectionPoint + jtag_uart_0.avalon_jtag_slave + false + true + true + true + + + java.lang.String + clk + false + true + false + true + + + java.lang.String + reset + false + true + false + true + + + java.lang.Integer + + false + true + true + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + true + true + + + com.altera.sopcmodel.interrupt.InterruptConnectionPoint$EIrqScheme + NONE + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + interrupt + false + + av_irq + Output + 1 + irq + + + + + + + int + 32 + false + true + true + true + + + java.math.BigInteger + 4294967295 + false + true + true + true + + + java.math.BigInteger + 79764919 + false + true + true + true + + + int + 1 + false + true + true + true + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 4294967295 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + java.lang.String + + true + true + false + true + + + int + 3 + true + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.custominstruction.CustomInstruction$ClockCycleType + VARIABLE + true + true + true + true + + + int + 0 + true + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 1 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios_custom_instruction + false + + clk + Input + 1 + clk + + + clk_en + Input + 1 + clk_en + + + dataa + Input + 32 + dataa + + + done + Output + 1 + done + + + n + Input + 3 + n + + + reset + Input + 1 + reset + + + result + Output + 32 + result + + + start + Input + 1 + start + + + + + + + debug.hostConnection + type jtag id 70:34|110:135 + + + embeddedsw.CMacro.BIG_ENDIAN + 0 + + + embeddedsw.CMacro.BREAK_ADDR + 0x00820820 + + + embeddedsw.CMacro.CPU_ARCH_NIOS2_R1 + + + + embeddedsw.CMacro.CPU_FREQ + 27000000u + + + embeddedsw.CMacro.CPU_ID_SIZE + 1 + + + embeddedsw.CMacro.CPU_ID_VALUE + 0x00000000 + + + embeddedsw.CMacro.CPU_IMPLEMENTATION + "tiny" + + + embeddedsw.CMacro.DATA_ADDR_WIDTH + 24 + + + embeddedsw.CMacro.DCACHE_LINE_SIZE + 0 + + + embeddedsw.CMacro.DCACHE_LINE_SIZE_LOG2 + 0 + + + embeddedsw.CMacro.DCACHE_SIZE + 0 + + + embeddedsw.CMacro.EXCEPTION_ADDR + 0x00810020 + + + embeddedsw.CMacro.FLASH_ACCELERATOR_LINES + 0 + + + embeddedsw.CMacro.FLASH_ACCELERATOR_LINE_SIZE + 0 + + + embeddedsw.CMacro.FLUSHDA_SUPPORTED + + + + embeddedsw.CMacro.HARDWARE_DIVIDE_PRESENT + 0 + + + embeddedsw.CMacro.HARDWARE_MULTIPLY_PRESENT + 0 + + + embeddedsw.CMacro.HARDWARE_MULX_PRESENT + 0 + + + embeddedsw.CMacro.HAS_DEBUG_CORE + 1 + + + embeddedsw.CMacro.HAS_DEBUG_STUB + + + + embeddedsw.CMacro.HAS_ILLEGAL_INSTRUCTION_EXCEPTION + + + + embeddedsw.CMacro.HAS_JMPI_INSTRUCTION + + + + embeddedsw.CMacro.ICACHE_LINE_SIZE + 0 + + + embeddedsw.CMacro.ICACHE_LINE_SIZE_LOG2 + 0 + + + embeddedsw.CMacro.ICACHE_SIZE + 0 + + + embeddedsw.CMacro.INST_ADDR_WIDTH + 24 + + + embeddedsw.CMacro.OCI_VERSION + 1 + + + embeddedsw.CMacro.RESET_ADDR + 0x00810000 + + + embeddedsw.configuration.DataCacheVictimBufImpl + ram + + + embeddedsw.configuration.HDLSimCachesCleared + 1 + + + embeddedsw.configuration.breakOffset + 32 + + + embeddedsw.configuration.breakSlave + nios2_qsys_0.debug_mem_slave + + + embeddedsw.configuration.cpuArchitecture + Nios II + + + embeddedsw.configuration.exceptionOffset + 32 + + + embeddedsw.configuration.exceptionSlave + onchip_memory2_0.s1 + + + embeddedsw.configuration.resetOffset + 0 + + + embeddedsw.configuration.resetSlave + onchip_memory2_0.s1 + + + embeddedsw.dts.compatible + altr,nios2-1.1 + + + embeddedsw.dts.group + cpu + + + embeddedsw.dts.name + nios2 + + + embeddedsw.dts.params.altr,exception-addr + 0x00810020 + + + embeddedsw.dts.params.altr,implementation + "tiny" + + + embeddedsw.dts.params.altr,reset-addr + 0x00810000 + + + embeddedsw.dts.params.clock-frequency + 27000000u + + + embeddedsw.dts.params.dcache-line-size + 0 + + + embeddedsw.dts.params.dcache-size + 0 + + + embeddedsw.dts.params.icache-line-size + 0 + + + embeddedsw.dts.params.icache-size + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + false + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + boolean + true + false + false + true + true + + + boolean + true + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + false + true + true + + + boolean + false + false + false + true + true + + + boolean + false + false + false + true + true + + + boolean + true + false + false + true + true + + + boolean + false + false + true + true + true + + + boolean + true + false + true + true + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + int + 8 + false + false + true + true + + + int + 8 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + true + true + true + + + int + 32 + false + true + true + true + + + int + 0 + false + true + true + true + + + int + 32 + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + onchip_memory2_0.s1 + false + true + true + true + + + java.lang.String + None + false + false + true + true + + + java.lang.String + onchip_memory2_0.s1 + false + true + true + true + + + java.lang.String + nios2_qsys_0.jtag_debug_module + false + true + false + true + + + java.lang.String + Internal + false + false + true + true + + + java.lang.String + Dynamic + false + false + true + true + + + int + 8 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + medium_le_shift + true + true + false + true + + + java.lang.String + no_mul + true + true + false + true + + + int + 0 + false + false + true + true + + + int + 2 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + false + true + true + + + java.lang.String + no_div + false + false + true + true + + + int + 12 + false + false + true + true + + + int + 12 + false + false + true + true + + + int + 4 + false + false + true + true + + + int + 6 + false + false + true + true + + + int + 7 + false + false + true + true + + + int + 16 + false + false + true + true + + + int + 8 + false + false + true + true + + + java.lang.String + Tiny + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 2 + false + false + true + true + + + int + 0 + false + false + true + true + + + java.lang.String + Automatic + false + true + false + true + + + java.lang.String + Automatic + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + None + false + false + true + true + + + java.lang.String + false + false + false + true + true + + + java.lang.String + ram + false + false + true + true + + + int + 0 + false + false + true + true + + + java.lang.String + Automatic + false + true + false + true + + + java.lang.String + Automatic + false + true + false + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + boolean + true + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + java.lang.String + Automatic + false + true + false + true + + + java.lang.String + Automatic + false + true + false + true + + + boolean + false + false + true + false + true + + + java.lang.String + Automatic + false + true + false + true + + + java.lang.String + Automatic + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + true + true + + + boolean + true + false + true + false + true + + + boolean + false + false + false + true + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + java.lang.String + _128 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + java.lang.String + none + false + false + true + true + + + java.lang.String + onchip_trace + false + false + true + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + long + 0 + false + true + false + true + + + int + 8454144 + true + true + true + true + + + int + 8454176 + true + true + true + true + + + int + 8521760 + true + true + false + true + + + int + 0 + true + true + true + true + + + java.lang.String + false + true + true + false + true + + + int + 0 + true + true + false + true + + + java.lang.String + nios2_qsys_0.debug_mem_slave + true + true + false + true + + + int + 32 + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + "synthesis translate_on" + true + true + false + true + + + java.lang.String + "synthesis translate_off" + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + int + 24 + false + true + false + true + ADDRESS_WIDTH + instruction_master + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + flash_instruction_master + + + int + 24 + false + true + false + true + ADDRESS_WIDTH + data_master + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_data_master_0 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_data_master_1 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_data_master_2 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_data_master_3 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_instruction_master_0 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_instruction_master_1 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_instruction_master_2 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + tightly_coupled_instruction_master_3 + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + data_master_high_performance + + + int + 1 + false + true + false + true + ADDRESS_WIDTH + instruction_master_high_performance + + + java.lang.String + ]]> + false + true + false + true + ADDRESS_MAP + instruction_master + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + flash_instruction_master + + + java.lang.String + ]]> + false + true + false + true + ADDRESS_MAP + data_master + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_data_master_0 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_data_master_1 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_data_master_2 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_data_master_3 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_instruction_master_0 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_instruction_master_1 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_instruction_master_2 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + tightly_coupled_instruction_master_3 + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + data_master_high_performance + + + java.lang.String + + false + true + false + true + ADDRESS_MAP + instruction_master_high_performance + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + long + 7 + false + true + false + true + INTERRUPTS_USED + irq + + + java.lang.String + ]]> + false + true + false + true + CUSTOM_INSTRUCTION_SLAVES + custom_instruction_master + + + java.lang.String + ]]> + false + true + false + true + CUSTOM_INSTRUCTION_SLAVES + custom_instruction_master_a + + + java.lang.String + ]]> + false + true + false + true + CUSTOM_INSTRUCTION_SLAVES + custom_instruction_master_b + + + java.lang.String + ]]> + false + true + false + true + CUSTOM_INSTRUCTION_SLAVES + custom_instruction_master_c + + + java.lang.String + ADDRESS_STALL 1 ADVANCED_INFO 0 ALLOWS_COMPILING_OTHER_FAMILY_IP 1 ANY_QFP 0 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 0 DSP_SHIFTER_BLOCK 0 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 1 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 ENABLE_PIN_PLANNER 0 ENGINEERING_SAMPLE 0 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FAMILY_LEVEL_INSTALLATION_ONLY 1 FASTEST 0 FINAL_TIMING_MODEL 0 FITTER_USE_FALLING_EDGE_DELAY 0 FPP_COMPLETELY_PLACES_AND_ROUTES_PERIPHERY 0 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 0 HARDCOPY 0 HAS_18_BIT_MULTS 0 HAS_ACE_SUPPORT 1 HAS_ACTIVE_PARALLEL_FLASH_SUPPORT 0 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 0 HAS_ADVANCED_IO_INVERTED_CORNER 0 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 0 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 0 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CDB_RE_NETWORK_PRESERVATION_SUPPORT 0 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 0 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DAP_JTAG_FROM_HPS 0 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 1 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 1 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 0 HAS_ERROR_DETECTION_SUPPORT 0 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_FUNCTIONAL_VERILOG_SIMULATION_SUPPORT 0 HAS_FUNCTIONAL_VHDL_SIMULATION_SUPPORT 0 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HARDCOPYII_SUPPORT 0 HAS_HC_READY_SUPPORT 0 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 0 HAS_IBISO_WRITER_SUPPORT 0 HAS_ICD_DATA_IP 0 HAS_IDB_SUPPORT 1 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 0 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_PLACEMENT_USING_GEOMETRY_RULE 0 HAS_IO_PLACEMENT_USING_PHYSIC_RULE 0 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NADDER_STYLE_FF 0 HAS_NADDER_STYLE_LCELL_COMB 0 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_NO_HARDBLOCK_PARTITION_SUPPORT 0 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PASSIVE_PARALLEL_SUPPORT 0 HAS_PHYSICAL_DESIGN_PLANNER_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 0 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_BINNING_LIMITS_DATA 0 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 0 HAS_PVA_SUPPORT 1 HAS_QUARTUS_HIERARCHICAL_DESIGN_SUPPORT 0 HAS_RAPID_RECOMPILE_SUPPORT 0 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_STRICT_PRESERVATION_SUPPORT 1 HAS_SYNTHESIS_ON_ATOMS 0 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TCL_FITTER_SUPPORT 0 HAS_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 0 HAS_U2B2_SUPPORT 0 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_USE_FITTER_INFO_SUPPORT 1 HAS_VCCPD_POWER_RAIL 0 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO2_WRITER_SUPPORT 0 HAS_XIBISO_WRITER_SUPPORT 1 IFP_USE_LEGACY_IO_CHECKER 0 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 INTERNAL_POF_SUPPORT_ENABLED 0 INTERNAL_USE_ONLY 0 ISSUE_MILITARY_TEMPERATURE_WARNING 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_FOR_INTERNAL_TESTING_ONLY 0 IS_HARDCOPY_FAMILY 0 IS_HBGA_PACKAGE 0 IS_HIGH_CURRENT_PART 0 IS_LOW_POWER_PART 0 IS_SDM_ONLY_PACKAGE 0 IS_SMI_PART 0 LOAD_BLK_TYPE_DATA_FROM_ATOM_WYS_INFO 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 0 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 0 MRAM_MEMORY 0 NOT_LISTED 0 NOT_MIGRATABLE 0 NO_FITTER_DELAY_CACHE_GENERATED 0 NO_PIN_OUT 0 NO_POF 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_ONLY 0 PROGRAMMER_SUPPORT 1 PVA_SUPPORTS_ONLY_SUBSET_OF_ATOMS 0 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 REQUIRE_QUARTUS_HIERARCHICAL_DESIGN 0 REQUIRE_SPECIAL_HANDLING_FOR_LOCAL_LABLINE 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RESTRICT_PARTIAL_RECONFIG 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SHOW_HIDDEN_FAMILY_IN_PROGRAMMER 0 STRICT_TIMING_DB_CHECKS 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 0 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 0 SUPPORTS_HIPI_RETIMING 0 SUPPORTS_MAC_CHAIN_OUT_ADDER 0 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 SUPPORTS_VID 0 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 0 TRANSCEIVER_6G_BLOCK 0 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ALTERA_LNSIM 0 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_NETWORK_ROUTING_POWER_CALCULATOR 0 USES_PART_INFO_FOR_DISPLAYING_CORE_VOLTAGE_VALUE 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_PVAFAM2 0 USES_SECOND_GENERATION_PART_INFO 0 USES_SECOND_GENERATION_POWER_ANALYZER 0 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USES_U2B2_TIMING_MODELS 0 USES_XML_FORMAT_FOR_EMIF_PIN_MAP_FILE 0 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 1 USE_RELAX_IO_ASSIGNMENT_RULES 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 0 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 0 USING_28NM_OR_OLDER_TIMING_METHODOLOGY 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + false + true + false + true + DEVICE_FEATURES + + + java.lang.String + EP4CE15E22C8 + false + true + false + true + DEVICE + + + java.lang.String + 8 + false + true + false + true + DEVICE_SPEEDGRADE + + + java.lang.Integer + 1 + false + true + false + true + CLOCK_DOMAIN + clk + + + java.lang.Integer + 1 + false + true + false + true + RESET_DOMAIN + clk + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + reset_req + Input + 1 + reset_req + + + + + + debug.providesServices + master + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + int + 1 + false + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + SYMBOLS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + boolean + true + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + boolean + false + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 32 + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + true + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + true + + d_address + Output + 24 + address + + + d_byteenable + Output + 4 + byteenable + + + d_read + Output + 1 + read + + + d_readdata + Input + 32 + readdata + + + d_waitrequest + Input + 1 + waitrequest + + + d_write + Output + 1 + write + + + d_writedata + Output + 32 + writedata + + + debug_mem_slave_debugaccess_to_roms + Output + 1 + debugaccess + + + false + jtag_uart_0 + avalon_jtag_slave + jtag_uart_0.avalon_jtag_slave + 8524960 + 8 + + + false + Altera_UP_SD_Card_Avalon_Interface_0 + avalon_sdcard_slave + Altera_UP_SD_Card_Avalon_Interface_0.avalon_sdcard_slave + 8523776 + 1024 + + + false + i2c_opencores_0 + avalon_slave_0 + i2c_opencores_0.avalon_slave_0 + 8524832 + 32 + + + false + epcq_controller_0 + avl_csr + epcq_controller_0.avl_csr + 8524800 + 32 + + + false + epcq_controller_0 + avl_mem + epcq_controller_0.avl_mem + 0 + 8388608 + + + false + nios2_qsys_0 + debug_mem_slave + nios2_qsys_0.debug_mem_slave + 8521728 + 2048 + + + false + onchip_memory2_0 + s1 + onchip_memory2_0.s1 + 8454144 + 36864 + + + false + pio_0 + s1 + pio_0.s1 + 8524944 + 16 + + + false + pio_1 + s1 + pio_1.s1 + 8524928 + 16 + + + false + pio_2 + s1 + pio_2.s1 + 8524912 + 16 + + + false + pio_3 + s1 + pio_3.s1 + 8524896 + 16 + + + false + pio_4 + s1 + pio_4.s1 + 8524880 + 16 + + + false + pio_5 + s1 + pio_5.s1 + 8524864 + 16 + + + + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + int + 1 + false + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + SYMBOLS + false + true + true + true + + + boolean + true + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + boolean + false + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + true + true + + + int + 32 + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + true + + i_address + Output + 24 + address + + + i_read + Output + 1 + read + + + i_readdata + Input + 32 + readdata + + + i_waitrequest + Input + 1 + waitrequest + + + false + nios2_qsys_0 + debug_mem_slave + nios2_qsys_0.debug_mem_slave + 8521728 + 2048 + + + false + onchip_memory2_0 + s1 + onchip_memory2_0.s1 + 8454144 + 36864 + + + + + + com.altera.entityinterfaces.IConnectionPoint + nios2_qsys_0.data_master + false + true + true + true + + + java.lang.String + clk + false + true + false + true + + + java.lang.String + reset + false + true + false + true + + + java.lang.String + + false + true + false + true + + + com.altera.sopcmodel.interrupt.InterruptConnectionPoint$EIrqScheme + INDIVIDUAL_REQUESTS + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + interrupt + true + + irq + Input + 32 + irq + + + false + i2c_opencores_0 + interrupt_sender + i2c_opencores_0.interrupt_sender + 0 + + + false + epcq_controller_0 + interrupt_sender + epcq_controller_0.interrupt_sender + 1 + + + false + jtag_uart_0 + irq + jtag_uart_0.irq + 2 + + + + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + + false + true + true + true + + + [Ljava.lang.String; + none + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + true + + debug_reset_request + Output + 1 + reset + + + + + + embeddedsw.configuration.hideDevice + 1 + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 1 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + qsys.ui.connect + instruction_master,data_master + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + DYNAMIC + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 2048 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + 0 + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + false + true + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + false + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + false + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + false + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + debug_mem_slave_address + Input + 9 + address + + + debug_mem_slave_byteenable + Input + 4 + byteenable + + + debug_mem_slave_debugaccess + Input + 1 + debugaccess + + + debug_mem_slave_read + Input + 1 + read + + + debug_mem_slave_readdata + Output + 32 + readdata + + + debug_mem_slave_waitrequest + Output + 1 + waitrequest + + + debug_mem_slave_write + Input + 1 + write + + + debug_mem_slave_writedata + Input + 32 + writedata + + + + + + java.lang.String + + true + true + false + true + + + int + 8 + false + true + false + true + + + int + 0 + false + false + true + true + + + boolean + false + false + true + false + true + + + int + 8 + false + true + false + true + + + int + 0 + true + true + false + true + + + boolean + true + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios_custom_instruction + true + + E_ci_multi_done + Input + 1 + done + + + E_ci_multi_clk_en + Output + 1 + clk_en + + + E_ci_multi_start + Output + 1 + start + + + E_ci_result + Input + 32 + result + + + D_ci_a + Output + 5 + a + + + D_ci_b + Output + 5 + b + + + D_ci_c + Output + 5 + c + + + D_ci_n + Output + 8 + n + + + D_ci_readra + Output + 1 + readra + + + D_ci_readrb + Output + 1 + readrb + + + D_ci_writerc + Output + 1 + writerc + + + E_ci_dataa + Output + 32 + dataa + + + E_ci_datab + Output + 32 + datab + + + E_ci_multi_clock + Output + 1 + clk + + + E_ci_multi_reset + Output + 1 + reset + + + E_ci_multi_reset_req + Output + 1 + reset_req + + + W_ci_estatus + Output + 1 + estatus + + + W_ci_ipending + Output + 32 + ipending + + + false + nios2_hw_crc32_0 + nios_custom_instruction_slave + nios2_hw_crc32_0.nios_custom_instruction_slave + 0 + nios2_hw_crc32_0 + + + false + nios_custom_instr_endianconverter_0 + s1 + nios_custom_instr_endianconverter_0.s1 + 8 + nios_custom_instr_endianconverter_0 + + + false + nios_custom_instr_bitswap_0 + s1 + nios_custom_instr_bitswap_0.s1 + 9 + nios_custom_instr_bitswap_0 + + + + + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + java.lang.String + Cyclone IV E + false + true + false + true + DEVICE_FAMILY + + + boolean + false + false + true + true + true + + + + + java.lang.String + + true + true + false + true + + + int + 0 + true + true + false + true + + + int + 1 + false + false + true + true + + + com.altera.sopcmodel.custominstruction.CustomInstruction$ClockCycleType + COMBINATORIAL + true + true + true + true + + + int + 0 + true + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 1 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios_custom_instruction + false + + dataa + Input + 32 + dataa + + + datab + Input + 32 + datab + + + result + Output + 32 + result + + + + + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + java.lang.String + Cyclone IV E + false + true + false + true + DEVICE_FAMILY + + + boolean + false + false + true + true + true + + + + + java.lang.String + + true + true + false + true + + + int + 0 + true + true + false + true + + + int + 1 + false + false + true + true + + + com.altera.sopcmodel.custominstruction.CustomInstruction$ClockCycleType + COMBINATORIAL + true + true + true + true + + + int + 0 + true + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 1 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios_custom_instruction + false + + dataa + Input + 32 + dataa + + + datab + Input + 32 + datab + + + result + Output + 32 + result + + + + + + + embeddedsw.CMacro.ALLOW_IN_SYSTEM_MEMORY_CONTENT_EDITOR + 0 + + + embeddedsw.CMacro.ALLOW_MRAM_SIM_CONTENTS_ONLY_FILE + 0 + + + embeddedsw.CMacro.CONTENTS_INFO + "" + + + embeddedsw.CMacro.DUAL_PORT + 0 + + + embeddedsw.CMacro.GUI_RAM_BLOCK_TYPE + AUTO + + + embeddedsw.CMacro.INIT_CONTENTS_FILE + sys_onchip_memory2_0 + + + embeddedsw.CMacro.INIT_MEM_CONTENT + 1 + + + embeddedsw.CMacro.INSTANCE_ID + NONE + + + embeddedsw.CMacro.NON_DEFAULT_INIT_FILE_ENABLED + 0 + + + embeddedsw.CMacro.RAM_BLOCK_TYPE + AUTO + + + embeddedsw.CMacro.READ_DURING_WRITE_MODE + DONT_CARE + + + embeddedsw.CMacro.SINGLE_CLOCK_OP + 0 + + + embeddedsw.CMacro.SIZE_MULTIPLE + 1 + + + embeddedsw.CMacro.SIZE_VALUE + 36864 + + + embeddedsw.CMacro.WRITABLE + 1 + + + embeddedsw.memoryInfo.DAT_SYM_INSTALL_DIR + SIM_DIR + + + embeddedsw.memoryInfo.GENERATE_DAT_SYM + 1 + + + embeddedsw.memoryInfo.GENERATE_HEX + 1 + + + embeddedsw.memoryInfo.HAS_BYTE_LANE + 0 + + + embeddedsw.memoryInfo.HEX_INSTALL_DIR + QPF_DIR + + + embeddedsw.memoryInfo.MEM_INIT_DATA_WIDTH + 32 + + + embeddedsw.memoryInfo.MEM_INIT_FILENAME + sys_onchip_memory2_0 + + + postgeneration.simulation.init_file.param_name + INIT_FILE + + + postgeneration.simulation.init_file.type + MEM_INIT + + + boolean + false + false + true + true + true + + + java.lang.String + AUTO + false + true + true + true + + + int + 32 + false + true + true + true + + + boolean + false + false + true + true + true + + + boolean + true + false + true + true + true + + + java.lang.String + onchip_mem.hex + false + false + true + true + + + java.lang.String + NONE + false + false + true + true + + + long + 36864 + false + true + true + true + + + java.lang.String + DONT_CARE + false + false + true + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + boolean + false + false + false + true + true + + + int + 1 + false + true + true + true + + + int + 1 + false + false + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + false + false + true + + + boolean + false + false + false + true + true + + + boolean + true + false + true + true + true + + + boolean + false + false + true + true + true + + + boolean + true + false + true + true + true + + + java.lang.String + sys_onchip_memory2_0 + false + true + false + true + UNIQUE_ID + + + java.lang.String + CYCLONEIVE + false + true + false + true + DEVICE_FAMILY + + + java.lang.String + ADDRESS_STALL 1 ADVANCED_INFO 0 ALLOWS_COMPILING_OTHER_FAMILY_IP 1 ANY_QFP 0 CELL_LEVEL_BACK_ANNOTATION_DISABLED 0 COMPILER_SUPPORT 1 DSP 0 DSP_SHIFTER_BLOCK 0 DUMP_ASM_LAB_BITS_FOR_POWER 1 EMUL 1 ENABLE_ADVANCED_IO_ANALYSIS_GUI_FEATURES 1 ENABLE_PIN_PLANNER 0 ENGINEERING_SAMPLE 0 EPCS 1 ESB 0 FAKE1 0 FAKE2 0 FAKE3 0 FAMILY_LEVEL_INSTALLATION_ONLY 1 FASTEST 0 FINAL_TIMING_MODEL 0 FITTER_USE_FALLING_EDGE_DELAY 0 FPP_COMPLETELY_PLACES_AND_ROUTES_PERIPHERY 0 GENERATE_DC_ON_CURRENT_WARNING_FOR_INTERNAL_CLAMPING_DIODE 0 HARDCOPY 0 HAS_18_BIT_MULTS 0 HAS_ACE_SUPPORT 1 HAS_ACTIVE_PARALLEL_FLASH_SUPPORT 0 HAS_ADJUSTABLE_OUTPUT_IO_TIMING_MEAS_POINT 0 HAS_ADVANCED_IO_INVERTED_CORNER 0 HAS_ADVANCED_IO_POWER_SUPPORT 1 HAS_ADVANCED_IO_TIMING_SUPPORT 1 HAS_ALM_SUPPORT 0 HAS_ATOM_AND_ROUTING_POWER_MODELED_TOGETHER 0 HAS_AUTO_DERIVE_CLOCK_UNCERTAINTY_SUPPORT 0 HAS_AUTO_FIT_SUPPORT 1 HAS_BALANCED_OPT_TECHNIQUE_SUPPORT 1 HAS_BENEFICIAL_SKEW_SUPPORT 1 HAS_BITLEVEL_DRIVE_STRENGTH_CONTROL 1 HAS_BSDL_FILE_GENERATION 1 HAS_CDB_RE_NETWORK_PRESERVATION_SUPPORT 0 HAS_CGA_SUPPORT 1 HAS_CHECK_NETLIST_SUPPORT 0 HAS_CLOCK_REGION_CHECKER_ENABLED 1 HAS_CORE_JUNCTION_TEMP_DERATING 0 HAS_CROSSTALK_SUPPORT 0 HAS_CUSTOM_REGION_SUPPORT 1 HAS_DAP_JTAG_FROM_HPS 0 HAS_DATA_DRIVEN_ACVQ_HSSI_SUPPORT 0 HAS_DDB_FDI_SUPPORT 0 HAS_DESIGN_ANALYZER_SUPPORT 1 HAS_DETAILED_IO_RAIL_POWER_MODEL 1 HAS_DETAILED_LEIM_STATIC_POWER_MODEL 1 HAS_DETAILED_LE_POWER_MODEL 1 HAS_DETAILED_ROUTING_MUX_STATIC_POWER_MODEL 1 HAS_DETAILED_THERMAL_CIRCUIT_PARAMETER_SUPPORT 1 HAS_DEVICE_MIGRATION_SUPPORT 1 HAS_DIAGONAL_MIGRATION_SUPPORT 0 HAS_EMIF_TOOLKIT_SUPPORT 0 HAS_ERROR_DETECTION_SUPPORT 0 HAS_FAMILY_VARIANT_MIGRATION_SUPPORT 0 HAS_FANOUT_FREE_NODE_SUPPORT 1 HAS_FAST_FIT_SUPPORT 1 HAS_FITTER_ECO_SUPPORT 1 HAS_FIT_NETLIST_OPT_RETIME_SUPPORT 1 HAS_FIT_NETLIST_OPT_SUPPORT 1 HAS_FORMAL_VERIFICATION_SUPPORT 1 HAS_FPGA_XCHANGE_SUPPORT 1 HAS_FSAC_LUTRAM_REGISTER_PACKING_SUPPORT 0 HAS_FULL_DAT_MIN_TIMING_SUPPORT 1 HAS_FULL_INCREMENTAL_DESIGN_SUPPORT 1 HAS_FUNCTIONAL_SIMULATION_SUPPORT 1 HAS_FUNCTIONAL_VERILOG_SIMULATION_SUPPORT 0 HAS_FUNCTIONAL_VHDL_SIMULATION_SUPPORT 0 HAS_GLITCH_FILTERING_SUPPORT 1 HAS_HARDCOPYII_SUPPORT 0 HAS_HC_READY_SUPPORT 0 HAS_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_HOLD_TIME_AVOIDANCE_ACROSS_CLOCK_SPINE_SUPPORT 1 HAS_HSPICE_WRITER_SUPPORT 1 HAS_HSSI_POWER_CALCULATOR 0 HAS_IBISO_WRITER_SUPPORT 0 HAS_ICD_DATA_IP 0 HAS_IDB_SUPPORT 1 HAS_INCREMENTAL_DAT_SUPPORT 1 HAS_INCREMENTAL_SYNTHESIS_SUPPORT 1 HAS_IO_ASSIGNMENT_ANALYSIS_SUPPORT 1 HAS_IO_DECODER 0 HAS_IO_PLACEMENT_OPTIMIZATION_SUPPORT 1 HAS_IO_PLACEMENT_USING_GEOMETRY_RULE 0 HAS_IO_PLACEMENT_USING_PHYSIC_RULE 0 HAS_IO_SMART_RECOMPILE_SUPPORT 0 HAS_JITTER_SUPPORT 1 HAS_JTAG_SLD_HUB_SUPPORT 1 HAS_LOGIC_LOCK_SUPPORT 1 HAS_MICROPROCESSOR 0 HAS_MIF_SMART_COMPILE_SUPPORT 1 HAS_MINMAX_TIMING_MODELING_SUPPORT 1 HAS_MIN_TIMING_ANALYSIS_SUPPORT 1 HAS_MUX_RESTRUCTURE_SUPPORT 1 HAS_NADDER_STYLE_FF 0 HAS_NADDER_STYLE_LCELL_COMB 0 HAS_NEW_HC_FLOW_SUPPORT 0 HAS_NEW_SERDES_MAX_RESOURCE_COUNT_REPORTING_SUPPORT 1 HAS_NEW_VPR_SUPPORT 1 HAS_NONSOCKET_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_NO_HARDBLOCK_PARTITION_SUPPORT 0 HAS_NO_JTAG_USERCODE_SUPPORT 0 HAS_OPERATING_SETTINGS_AND_CONDITIONS_REPORTING_SUPPORT 1 HAS_PAD_LOCATION_ASSIGNMENT_SUPPORT 0 HAS_PARTIAL_RECONFIG_SUPPORT 0 HAS_PASSIVE_PARALLEL_SUPPORT 0 HAS_PHYSICAL_DESIGN_PLANNER_SUPPORT 0 HAS_PHYSICAL_NETLIST_OUTPUT 0 HAS_PHYSICAL_ROUTING_SUPPORT 0 HAS_PIN_SPECIFIC_VOLTAGE_SUPPORT 1 HAS_PLDM_REF_SUPPORT 1 HAS_POWER_BINNING_LIMITS_DATA 0 HAS_POWER_ESTIMATION_SUPPORT 1 HAS_PRELIMINARY_CLOCK_UNCERTAINTY_NUMBERS 0 HAS_PRE_FITTER_FPP_SUPPORT 0 HAS_PRE_FITTER_LUTRAM_NETLIST_CHECKER_ENABLED 0 HAS_PVA_SUPPORT 1 HAS_QUARTUS_HIERARCHICAL_DESIGN_SUPPORT 0 HAS_RAPID_RECOMPILE_SUPPORT 0 HAS_RCF_SUPPORT 1 HAS_RCF_SUPPORT_FOR_DEBUGGING 0 HAS_RED_BLACK_SEPARATION_SUPPORT 0 HAS_RE_LEVEL_TIMING_GRAPH_SUPPORT 1 HAS_RISEFALL_DELAY_SUPPORT 1 HAS_SIGNAL_PROBE_SUPPORT 1 HAS_SIGNAL_TAP_SUPPORT 1 HAS_SIMULATOR_SUPPORT 0 HAS_SPLIT_IO_SUPPORT 1 HAS_SPLIT_LC_SUPPORT 1 HAS_STRICT_PRESERVATION_SUPPORT 1 HAS_SYNTHESIS_ON_ATOMS 0 HAS_SYNTH_FSYN_NETLIST_OPT_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_RETIME_SUPPORT 1 HAS_SYNTH_NETLIST_OPT_SUPPORT 1 HAS_TCL_FITTER_SUPPORT 0 HAS_TECHNOLOGY_MIGRATION_SUPPORT 0 HAS_TEMPLATED_REGISTER_PACKING_SUPPORT 1 HAS_TIME_BORROWING_SUPPORT 0 HAS_TIMING_DRIVEN_SYNTHESIS_SUPPORT 1 HAS_TIMING_INFO_SUPPORT 1 HAS_TIMING_OPERATING_CONDITIONS 1 HAS_TIMING_SIMULATION_SUPPORT 1 HAS_TITAN_BASED_MAC_REGISTER_PACKER_SUPPORT 0 HAS_U2B2_SUPPORT 0 HAS_USER_HIGH_SPEED_LOW_POWER_TILE_SUPPORT 0 HAS_USE_FITTER_INFO_SUPPORT 1 HAS_VCCPD_POWER_RAIL 0 HAS_VERTICAL_MIGRATION_SUPPORT 1 HAS_VIEWDRAW_SYMBOL_SUPPORT 0 HAS_VIO_SUPPORT 1 HAS_VIRTUAL_DEVICES 0 HAS_WYSIWYG_DFFEAS_SUPPORT 1 HAS_XIBISO2_WRITER_SUPPORT 0 HAS_XIBISO_WRITER_SUPPORT 1 IFP_USE_LEGACY_IO_CHECKER 0 INCREMENTAL_DESIGN_SUPPORTS_COMPATIBLE_CONSTRAINTS 1 INSTALLED 0 INTERNAL_POF_SUPPORT_ENABLED 0 INTERNAL_USE_ONLY 0 ISSUE_MILITARY_TEMPERATURE_WARNING 0 IS_CONFIG_ROM 0 IS_DEFAULT_FAMILY 0 IS_FOR_INTERNAL_TESTING_ONLY 0 IS_HARDCOPY_FAMILY 0 IS_HBGA_PACKAGE 0 IS_HIGH_CURRENT_PART 0 IS_LOW_POWER_PART 0 IS_SDM_ONLY_PACKAGE 0 IS_SMI_PART 0 LOAD_BLK_TYPE_DATA_FROM_ATOM_WYS_INFO 0 LVDS_IO 1 M10K_MEMORY 0 M144K_MEMORY 0 M20K_MEMORY 0 M4K_MEMORY 0 M512_MEMORY 0 M9K_MEMORY 1 MLAB_MEMORY 0 MRAM_MEMORY 0 NOT_LISTED 0 NOT_MIGRATABLE 0 NO_FITTER_DELAY_CACHE_GENERATED 0 NO_PIN_OUT 0 NO_POF 0 NO_RPE_SUPPORT 0 NO_SUPPORT_FOR_LOGICLOCK_CONTENT_BACK_ANNOTATION 1 NO_SUPPORT_FOR_STA_CLOCK_UNCERTAINTY_CHECK 0 NO_TDC_SUPPORT 0 POSTFIT_BAK_DATABASE_EXPORT_ENABLED 1 POSTMAP_BAK_DATABASE_EXPORT_ENABLED 1 PROGRAMMER_ONLY 0 PROGRAMMER_SUPPORT 1 PVA_SUPPORTS_ONLY_SUBSET_OF_ATOMS 0 QFIT_IN_DEVELOPMENT 0 QMAP_IN_DEVELOPMENT 0 RAM_LOGICAL_NAME_CHECKING_IN_CUT_ENABLED 1 REPORTS_METASTABILITY_MTBF 1 REQUIRES_INSTALLATION_PATCH 0 REQUIRES_LIST_OF_TEMPERATURE_AND_VOLTAGE_OPERATING_CONDITIONS 1 REQUIRE_QUARTUS_HIERARCHICAL_DESIGN 0 REQUIRE_SPECIAL_HANDLING_FOR_LOCAL_LABLINE 1 RESERVES_SIGNAL_PROBE_PINS 0 RESOLVE_MAX_FANOUT_EARLY 1 RESOLVE_MAX_FANOUT_LATE 0 RESPECTS_FIXED_SIZED_LOCKED_LOCATION_LOGICLOCK 1 RESTRICTED_USER_SELECTION 0 RESTRICT_PARTIAL_RECONFIG 0 RISEFALL_SUPPORT_IS_HIDDEN 0 SHOW_HIDDEN_FAMILY_IN_PROGRAMMER 0 STRICT_TIMING_DB_CHECKS 0 SUPPORTS_ADDITIONAL_OPTIONS_FOR_UNUSED_IO 0 SUPPORTS_CRC 1 SUPPORTS_DIFFERENTIAL_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_DSP_BALANCING_BACK_ANNOTATION 0 SUPPORTS_GENERATION_OF_EARLY_POWER_ESTIMATOR_FILE 1 SUPPORTS_GLOBAL_SIGNAL_BACK_ANNOTATION 0 SUPPORTS_HIPI_RETIMING 0 SUPPORTS_MAC_CHAIN_OUT_ADDER 0 SUPPORTS_RAM_PACKING_BACK_ANNOTATION 0 SUPPORTS_REG_PACKING_BACK_ANNOTATION 0 SUPPORTS_SIGNALPROBE_REGISTER_PIPELINING 1 SUPPORTS_SINGLE_ENDED_AIOT_BOARD_TRACE_MODEL 1 SUPPORTS_USER_MANUAL_LOGIC_DUPLICATION 1 SUPPORTS_VID 0 TMV_RUN_CUSTOMIZABLE_VIEWER 1 TMV_RUN_INTERNAL_DETAILS 1 TMV_RUN_INTERNAL_DETAILS_ON_IO 0 TMV_RUN_INTERNAL_DETAILS_ON_IOBUF 1 TMV_RUN_INTERNAL_DETAILS_ON_LCELL 0 TMV_RUN_INTERNAL_DETAILS_ON_LRAM 0 TRANSCEIVER_3G_BLOCK 0 TRANSCEIVER_6G_BLOCK 0 USES_ACV_FOR_FLED 1 USES_ADB_FOR_BACK_ANNOTATION 1 USES_ALTERA_LNSIM 0 USES_ASIC_ROUTING_POWER_CALCULATOR 0 USES_DATA_DRIVEN_PLL_COMPUTATION_UTIL 1 USES_DEV 1 USES_ICP_FOR_ECO_FITTER 0 USES_LIBERTY_TIMING 0 USES_NETWORK_ROUTING_POWER_CALCULATOR 0 USES_PART_INFO_FOR_DISPLAYING_CORE_VOLTAGE_VALUE 0 USES_POWER_SIGNAL_ACTIVITIES 1 USES_PVAFAM2 0 USES_SECOND_GENERATION_PART_INFO 0 USES_SECOND_GENERATION_POWER_ANALYZER 0 USES_THIRD_GENERATION_TIMING_MODELS_TIS 1 USES_U2B2_TIMING_MODELS 0 USES_XML_FORMAT_FOR_EMIF_PIN_MAP_FILE 0 USE_ADVANCED_IO_POWER_BY_DEFAULT 1 USE_ADVANCED_IO_TIMING_BY_DEFAULT 1 USE_BASE_FAMILY_DDB_PATH 0 USE_OCT_AUTO_CALIBRATION 1 USE_RELAX_IO_ASSIGNMENT_RULES 0 USE_RISEFALL_ONLY 1 USE_SEPARATE_LIST_FOR_TECH_MIGRATION 0 USE_SINGLE_COMPILER_PASS_PLL_MIF_FILE_WRITER 1 USE_TITAN_IO_BASED_IO_REGISTER_PACKER_UTIL 0 USING_28NM_OR_OLDER_TIMING_METHODOLOGY 1 WYSIWYG_BUS_WIDTH_CHECKING_IN_CUT_ENABLED 1 + false + true + false + true + DEVICE_FEATURES + + + int + 14 + true + true + false + true + + + int + 32 + true + true + false + true + + + java.lang.String + Automatic + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + sys_onchip_memory2_0.hex + true + true + false + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clock + false + + clk + Input + 1 + clk + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 1 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + DYNAMIC + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 36864 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk1 + false + true + true + true + + + java.lang.String + reset1 + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 36864 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + true + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 1 + false + true + true + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 14 + address + + + clken + Input + 1 + clken + + + chipselect + Input + 1 + chipselect + + + write + Input + 1 + write + + + readdata + Output + 32 + readdata + + + writedata + Input + 32 + writedata + + + byteenable + Input + 4 + byteenable + + + + + + java.lang.String + clk1 + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset + Input + 1 + reset + + + reset_req + Input + 1 + reset_req + + + + + + + embeddedsw.CMacro.BIT_CLEARING_EDGE_REGISTER + 0 + + + embeddedsw.CMacro.BIT_MODIFYING_OUTPUT_REGISTER + 0 + + + embeddedsw.CMacro.CAPTURE + 0 + + + embeddedsw.CMacro.DATA_WIDTH + 8 + + + embeddedsw.CMacro.DO_TEST_BENCH_WIRING + 0 + + + embeddedsw.CMacro.DRIVEN_SIM_VALUE + 0 + + + embeddedsw.CMacro.EDGE_TYPE + NONE + + + embeddedsw.CMacro.FREQ + 27000000 + + + embeddedsw.CMacro.HAS_IN + 0 + + + embeddedsw.CMacro.HAS_OUT + 1 + + + embeddedsw.CMacro.HAS_TRI + 0 + + + embeddedsw.CMacro.IRQ_TYPE + NONE + + + embeddedsw.CMacro.RESET_VALUE + 0 + + + embeddedsw.dts.compatible + altr,pio-1.0 + + + embeddedsw.dts.group + gpio + + + embeddedsw.dts.name + pio + + + embeddedsw.dts.params.altr,gpio-bank-width + 8 + + + embeddedsw.dts.params.resetvalue + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + false + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + Output + false + true + true + true + + + java.lang.String + RISING + false + false + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + LEVEL + false + false + true + true + + + long + 0 + false + true + true + true + + + boolean + false + false + false + true + true + + + long + 0 + false + false + true + true + + + int + 8 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + boolean + false + true + true + false + true + + + boolean + true + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 4 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 2 + address + + + write_n + Input + 1 + write_n + + + writedata + Input + 32 + writedata + + + chipselect + Input + 1 + chipselect + + + readdata + Output + 32 + readdata + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + out_port + Output + 8 + export + + + + + + + embeddedsw.CMacro.BIT_CLEARING_EDGE_REGISTER + 0 + + + embeddedsw.CMacro.BIT_MODIFYING_OUTPUT_REGISTER + 0 + + + embeddedsw.CMacro.CAPTURE + 0 + + + embeddedsw.CMacro.DATA_WIDTH + 32 + + + embeddedsw.CMacro.DO_TEST_BENCH_WIRING + 0 + + + embeddedsw.CMacro.DRIVEN_SIM_VALUE + 0 + + + embeddedsw.CMacro.EDGE_TYPE + NONE + + + embeddedsw.CMacro.FREQ + 27000000 + + + embeddedsw.CMacro.HAS_IN + 1 + + + embeddedsw.CMacro.HAS_OUT + 0 + + + embeddedsw.CMacro.HAS_TRI + 0 + + + embeddedsw.CMacro.IRQ_TYPE + NONE + + + embeddedsw.CMacro.RESET_VALUE + 0 + + + embeddedsw.dts.compatible + altr,pio-1.0 + + + embeddedsw.dts.group + gpio + + + embeddedsw.dts.name + pio + + + embeddedsw.dts.params.altr,gpio-bank-width + 32 + + + embeddedsw.dts.params.resetvalue + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + false + true + true + + + boolean + false + false + false + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + Input + false + true + true + true + + + java.lang.String + RISING + false + false + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + LEVEL + false + false + true + true + + + long + 0 + false + false + true + true + + + boolean + false + false + true + true + true + + + long + 0 + false + false + true + true + + + int + 32 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + true + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 4 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 2 + address + + + readdata + Output + 32 + readdata + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + in_port + Input + 32 + export + + + + + + + embeddedsw.CMacro.BIT_CLEARING_EDGE_REGISTER + 0 + + + embeddedsw.CMacro.BIT_MODIFYING_OUTPUT_REGISTER + 0 + + + embeddedsw.CMacro.CAPTURE + 0 + + + embeddedsw.CMacro.DATA_WIDTH + 32 + + + embeddedsw.CMacro.DO_TEST_BENCH_WIRING + 0 + + + embeddedsw.CMacro.DRIVEN_SIM_VALUE + 0 + + + embeddedsw.CMacro.EDGE_TYPE + NONE + + + embeddedsw.CMacro.FREQ + 27000000 + + + embeddedsw.CMacro.HAS_IN + 0 + + + embeddedsw.CMacro.HAS_OUT + 1 + + + embeddedsw.CMacro.HAS_TRI + 0 + + + embeddedsw.CMacro.IRQ_TYPE + NONE + + + embeddedsw.CMacro.RESET_VALUE + 0 + + + embeddedsw.dts.compatible + altr,pio-1.0 + + + embeddedsw.dts.group + gpio + + + embeddedsw.dts.name + pio + + + embeddedsw.dts.params.altr,gpio-bank-width + 32 + + + embeddedsw.dts.params.resetvalue + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + false + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + Output + false + true + true + true + + + java.lang.String + RISING + false + false + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + LEVEL + false + false + true + true + + + long + 0 + false + true + true + true + + + boolean + false + false + false + true + true + + + long + 0 + false + false + true + true + + + int + 32 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + boolean + false + true + true + false + true + + + boolean + true + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 4 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 2 + address + + + write_n + Input + 1 + write_n + + + writedata + Input + 32 + writedata + + + chipselect + Input + 1 + chipselect + + + readdata + Output + 32 + readdata + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + out_port + Output + 32 + export + + + + + + + embeddedsw.CMacro.BIT_CLEARING_EDGE_REGISTER + 0 + + + embeddedsw.CMacro.BIT_MODIFYING_OUTPUT_REGISTER + 0 + + + embeddedsw.CMacro.CAPTURE + 0 + + + embeddedsw.CMacro.DATA_WIDTH + 32 + + + embeddedsw.CMacro.DO_TEST_BENCH_WIRING + 0 + + + embeddedsw.CMacro.DRIVEN_SIM_VALUE + 0 + + + embeddedsw.CMacro.EDGE_TYPE + NONE + + + embeddedsw.CMacro.FREQ + 27000000 + + + embeddedsw.CMacro.HAS_IN + 0 + + + embeddedsw.CMacro.HAS_OUT + 1 + + + embeddedsw.CMacro.HAS_TRI + 0 + + + embeddedsw.CMacro.IRQ_TYPE + NONE + + + embeddedsw.CMacro.RESET_VALUE + 0 + + + embeddedsw.dts.compatible + altr,pio-1.0 + + + embeddedsw.dts.group + gpio + + + embeddedsw.dts.name + pio + + + embeddedsw.dts.params.altr,gpio-bank-width + 32 + + + embeddedsw.dts.params.resetvalue + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + false + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + Output + false + true + true + true + + + java.lang.String + RISING + false + false + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + LEVEL + false + false + true + true + + + long + 0 + false + true + true + true + + + boolean + false + false + false + true + true + + + long + 0 + false + false + true + true + + + int + 32 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + boolean + false + true + true + false + true + + + boolean + true + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 4 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 2 + address + + + write_n + Input + 1 + write_n + + + writedata + Input + 32 + writedata + + + chipselect + Input + 1 + chipselect + + + readdata + Output + 32 + readdata + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + out_port + Output + 32 + export + + + + + + + embeddedsw.CMacro.BIT_CLEARING_EDGE_REGISTER + 0 + + + embeddedsw.CMacro.BIT_MODIFYING_OUTPUT_REGISTER + 0 + + + embeddedsw.CMacro.CAPTURE + 0 + + + embeddedsw.CMacro.DATA_WIDTH + 32 + + + embeddedsw.CMacro.DO_TEST_BENCH_WIRING + 0 + + + embeddedsw.CMacro.DRIVEN_SIM_VALUE + 0 + + + embeddedsw.CMacro.EDGE_TYPE + NONE + + + embeddedsw.CMacro.FREQ + 27000000 + + + embeddedsw.CMacro.HAS_IN + 1 + + + embeddedsw.CMacro.HAS_OUT + 0 + + + embeddedsw.CMacro.HAS_TRI + 0 + + + embeddedsw.CMacro.IRQ_TYPE + NONE + + + embeddedsw.CMacro.RESET_VALUE + 0 + + + embeddedsw.dts.compatible + altr,pio-1.0 + + + embeddedsw.dts.group + gpio + + + embeddedsw.dts.name + pio + + + embeddedsw.dts.params.altr,gpio-bank-width + 32 + + + embeddedsw.dts.params.resetvalue + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + false + true + true + + + boolean + false + false + false + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + Input + false + true + true + true + + + java.lang.String + RISING + false + false + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + LEVEL + false + false + true + true + + + long + 0 + false + false + true + true + + + boolean + false + false + true + true + true + + + long + 0 + false + false + true + true + + + int + 32 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + true + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 4 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 2 + address + + + readdata + Output + 32 + readdata + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + in_port + Input + 32 + export + + + + + + + embeddedsw.CMacro.BIT_CLEARING_EDGE_REGISTER + 0 + + + embeddedsw.CMacro.BIT_MODIFYING_OUTPUT_REGISTER + 0 + + + embeddedsw.CMacro.CAPTURE + 0 + + + embeddedsw.CMacro.DATA_WIDTH + 8 + + + embeddedsw.CMacro.DO_TEST_BENCH_WIRING + 0 + + + embeddedsw.CMacro.DRIVEN_SIM_VALUE + 0 + + + embeddedsw.CMacro.EDGE_TYPE + NONE + + + embeddedsw.CMacro.FREQ + 27000000 + + + embeddedsw.CMacro.HAS_IN + 0 + + + embeddedsw.CMacro.HAS_OUT + 1 + + + embeddedsw.CMacro.HAS_TRI + 0 + + + embeddedsw.CMacro.IRQ_TYPE + NONE + + + embeddedsw.CMacro.RESET_VALUE + 0 + + + embeddedsw.dts.compatible + altr,pio-1.0 + + + embeddedsw.dts.group + gpio + + + embeddedsw.dts.name + pio + + + embeddedsw.dts.params.altr,gpio-bank-width + 8 + + + embeddedsw.dts.params.resetvalue + 0 + + + embeddedsw.dts.vendor + altr + + + boolean + false + false + false + true + true + + + boolean + false + false + true + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + Output + false + true + true + true + + + java.lang.String + RISING + false + false + true + true + + + boolean + false + false + false + true + true + + + java.lang.String + LEVEL + false + false + true + true + + + long + 0 + false + true + true + true + + + boolean + false + false + false + true + true + + + long + 0 + false + false + true + true + + + int + 8 + false + true + true + true + + + long + 27000000 + false + true + false + true + CLOCK_RATE + clk + + + boolean + false + true + true + false + true + + + boolean + true + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + java.lang.String + NONE + true + true + false + true + + + boolean + false + true + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + + + boolean + false + false + true + false + true + + + java.lang.String + + false + true + false + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.Boolean + true + true + true + false + true + + + java.lang.Long + 27000000 + true + true + false + true + + clock + false + + clk + Input + 1 + clk + + + + + + java.lang.String + clk + false + true + true + true + + + com.altera.sopcmodel.reset.Reset$Edges + DEASSERT + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + reset + false + + reset_n + Input + 1 + reset_n + + + + + + embeddedsw.configuration.isFlash + 0 + + + embeddedsw.configuration.isMemoryDevice + 0 + + + embeddedsw.configuration.isNonVolatileStorage + 0 + + + embeddedsw.configuration.isPrintableDevice + 0 + + + com.altera.sopcmodel.avalon.AvalonConnectionPoint$AddressAlignment + NATIVE + false + true + false + true + + + int + 0 + false + true + false + true + + + java.math.BigInteger + 4 + true + true + false + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.lang.String + clk + false + true + true + true + + + java.lang.String + reset + false + true + true + true + + + int + 8 + false + true + true + true + + + java.math.BigInteger + + false + true + false + true + + + com.altera.entityinterfaces.IConnectionPoint + + false + true + false + true + + + boolean + false + false + true + true + true + + + com.altera.sopcmodel.avalon.EAddrBurstUnits + WORDS + false + true + true + true + + + boolean + false + false + true + false + true + + + java.math.BigInteger + 0 + false + true + true + true + + + int + 0 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + true + true + + + int + 0 + false + false + true + true + + + int + 0 + false + false + true + true + + + int + 1 + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + int + 1 + false + true + false + true + + + int + 1 + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + true + true + + + com.altera.sopcmodel.avalon.TimingUnits + Cycles + false + true + true + true + + + boolean + false + false + true + false + true + + + boolean + false + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + false + true + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + avalon + false + + address + Input + 2 + address + + + write_n + Input + 1 + write_n + + + writedata + Input + 32 + writedata + + + chipselect + Input + 1 + chipselect + + + readdata + Output + 32 + readdata + + + + + + java.lang.String + + false + true + true + true + + + java.lang.String + + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + conduit + false + + out_port + Output + 8 + export + + + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x008214a0 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + jtag_uart_0 + avalon_jtag_slave + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821000 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + Altera_UP_SD_Card_Avalon_Interface_0 + avalon_sdcard_slave + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821420 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + i2c_opencores_0 + avalon_slave_0 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821400 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + epcq_controller_0 + avl_csr + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x0000 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + epcq_controller_0 + avl_mem + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00820800 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + nios2_qsys_0 + debug_mem_slave + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00810000 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + onchip_memory2_0 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821490 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + pio_0 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821480 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + pio_1 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821470 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + pio_2 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821460 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + pio_3 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821450 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + pio_4 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00821440 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + data_master + pio_5 + s1 + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00820800 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + instruction_master + nios2_qsys_0 + debug_mem_slave + + + + int + 1 + false + true + true + true + + + java.math.BigInteger + 0x00810000 + false + true + true + true + + + boolean + false + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + instruction_master + onchip_memory2_0 + s1 + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + nios2_qsys_0 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + jtag_uart_0 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + pio_0 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + pio_1 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + pio_2 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + pio_3 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + pio_4 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + Altera_UP_SD_Card_Avalon_Interface_0 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + pio_5 + clk + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + onchip_memory2_0 + clk1 + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + i2c_opencores_0 + clock + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk + epcq_controller_0 + clock_sink + + + + int + 0 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + irq + i2c_opencores_0 + interrupt_sender + + + + int + 1 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + irq + epcq_controller_0 + interrupt_sender + + + + int + 2 + false + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + irq + jtag_uart_0 + irq + + + + java.lang.String + nios2_hw_crc32_0 + false + true + true + true + + + java.lang.String + + true + true + true + true + + + int + 1 + false + true + false + true + + + long + 0 + false + true + true + true + + + int + -1 + true + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + custom_instruction_master + nios2_hw_crc32_0 + nios_custom_instruction_slave + + + + java.lang.String + nios_custom_instr_endianconverter_0 + false + true + true + true + + + java.lang.String + + true + true + true + true + + + int + 1 + false + true + false + true + + + long + 8 + false + true + true + true + + + int + -1 + true + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + custom_instruction_master + nios_custom_instr_endianconverter_0 + s1 + + + + java.lang.String + nios_custom_instr_bitswap_0 + false + true + true + true + + + java.lang.String + + true + true + true + true + + + int + 1 + false + true + false + true + + + long + 9 + false + true + true + true + + + int + -1 + true + true + true + true + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + nios2_qsys_0 + custom_instruction_master + nios_custom_instr_bitswap_0 + s1 + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + i2c_opencores_0 + clock_reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + nios2_qsys_0 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + jtag_uart_0 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + pio_0 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + pio_1 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + pio_2 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + pio_3 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + pio_4 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + Altera_UP_SD_Card_Avalon_Interface_0 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + epcq_controller_0 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + pio_5 + reset + + + + java.lang.String + UNKNOWN + false + true + true + true + + + boolean + false + false + true + true + true + + clk_27 + clk_reset + onchip_memory2_0 + reset1 + + + 1 + Altera_UP_SD_Card_Avalon_Interface_mod + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + SD Card Interface + 15.1 + + + 13 + avalon_slave + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Avalon Memory Mapped Slave + 15.1 + + + 12 + clock_sink + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Clock Input + 15.1 + + + 12 + reset_sink + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Reset Input + 15.1 + + + 8 + conduit_end + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Conduit + 15.1 + + + 1 + clock_source + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + Clock Source + 15.1 + + + 1 + clock_sink + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Clock Input + 15.1 + + + 1 + reset_sink + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Reset Input + 15.1 + + + 1 + clock_source + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Clock Output + 15.1 + + + 1 + reset_source + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Reset Output + 15.1 + + + 1 + altera_epcq_controller_mod + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + Altera Serial Flash Controller + 15.1 + + + 3 + interrupt_sender + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Interrupt Sender + 15.1 + + + 1 + i2c_opencores + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + I2C Master (opencores.org) + 13.0 + + + 1 + altera_avalon_jtag_uart + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + JTAG UART + 15.1 + + + 1 + nios2_hw_crc32 + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + nios2_hw_crc32 + 1.0 + + + 3 + nios_custom_instruction_slave + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Custom Instruction Slave + 15.1 + + + 1 + altera_nios2_gen2 + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + Nios II Processor + 15.1 + + + 2 + avalon_master + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Avalon Memory Mapped Master + 15.1 + + + 1 + interrupt_receiver + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Interrupt Receiver + 15.1 + + + 1 + reset_source + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Reset Output + 15.1 + + + 1 + nios_custom_instruction_master + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IMutableConnectionPoint + Custom Instruction Master + 15.1 + + + 1 + altera_nios_custom_instr_bitswap + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + Bitswap + 15.1 + + + 1 + altera_nios_custom_instr_endianconverter + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + Endian Converter + 100.99.98.97 + + + 1 + altera_avalon_onchip_memory2 + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + On-Chip Memory (RAM or ROM) + 15.1 + + + 6 + altera_avalon_pio + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IModule + PIO (Parallel I/O) + 15.1 + + + 15 + avalon + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IConnection + Avalon Memory Mapped Connection + 15.1 + + + 12 + clock + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IConnection + Clock Connection + 15.1 + + + 3 + interrupt + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IConnection + Interrupt Connection + 15.1 + + + 3 + nios_custom_instruction + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IConnection + Nios II Custom Instruction Connection + 15.1 + + + 12 + reset + com.altera.entityinterfaces.IElementClass + com.altera.entityinterfaces.IConnection + Reset Connection + 15.1 + + 15.1 185 + + diff --git a/tools/create_fw_img.c b/tools/create_fw_img.c new file mode 100644 index 0000000..f494371 --- /dev/null +++ b/tools/create_fw_img.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define HDR_SIZE 512 +#define BUF_SIZE 1024 +#define MAX_FILENAME 32 + +#define FW_KEY_SIZE 4 +#define FW_SUFFIX_MAX_SIZE 8 + +#define FW_HDR_LEN 26 + +static uint32_t crc32_tab[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +uint32_t +crc32(uint32_t crc, const void *buf, size_t size) +{ + const uint8_t *p; + + p = buf; + crc = crc ^ ~0U; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + + return crc ^ ~0U; +} + +int main(int argc, char **argv) +{ + unsigned char block; + + int fd_i, fd_o; + struct stat fileinfo; + char fw_bin_name[MAX_FILENAME]; + char hdrbuf[HDR_SIZE]; + char rdbuf[BUF_SIZE]; + unsigned fw_version_major; + unsigned fw_version_minor; + uint32_t hdr_crc; + uint32_t crc = 0; + + unsigned int i, bytes_read, bytes_written, tot_bytes_read = 0; + + if ((argc < 3) || (argc > 4)) { + printf("Usege: %s rbf version [version_suffix]\n", argv[0]); + return -1; + } + + if ((fd_i = open(argv[1], O_RDONLY)) == -1 || fstat(fd_i, &fileinfo) == -1) { + printf("Couldn't open input file\n"); + return -1; + } + + snprintf(fw_bin_name, MAX_FILENAME-1, "ossc_%s%s%s.bin", argv[2], (argc == 4) ? "-" : "", (argc == 4) ? argv[3] : ""); + + if ((fd_o = open(fw_bin_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) { + printf("Couldn't open output file\n"); + return -1; + } + + if ((sscanf(argv[2], "%u.%u", &fw_version_major, &fw_version_minor) != 2) || (fw_version_major > 255) || (fw_version_minor > 255)) { + printf("Invalid version format specified\n"); + return -1; + } + //printf("%s, %u.%u\n", argv[2], fw_version_major, (uint8_t)fw_version_minor); + + memset(hdrbuf, 0x00, HDR_SIZE); + snprintf(hdrbuf, FW_KEY_SIZE+1, "OSSC"); + hdrbuf[4] = (uint8_t)fw_version_major; + hdrbuf[5] = (uint8_t)fw_version_minor; + snprintf(hdrbuf+6, FW_SUFFIX_MAX_SIZE+1, (argc == 4) ? argv[3] : ""); + *((uint32_t*)(hdrbuf+6+FW_SUFFIX_MAX_SIZE)) = htonl(FW_HDR_LEN); + *((uint32_t*)(hdrbuf+6+FW_SUFFIX_MAX_SIZE+4)) = htonl((uint32_t)fileinfo.st_size); + + // data CRC + while ((bytes_read = read(fd_i, rdbuf, BUF_SIZE)) > 0) { + crc = crc32(crc, rdbuf, bytes_read); + tot_bytes_read += bytes_read; + } + *((uint32_t*)(hdrbuf+6+FW_SUFFIX_MAX_SIZE+8)) = htonl(crc); + + // header CRC + hdr_crc = crc32(0, hdrbuf, FW_HDR_LEN); + *((uint32_t*)(hdrbuf+HDR_SIZE-4)) = htonl(hdr_crc); + + if (tot_bytes_read != fileinfo.st_size) { + printf("Incorrect size output file\n"); + return -1; + } + + printf("version %u.%u%s%s: %u bytes\n", fw_version_major, fw_version_minor, (argc == 4) ? "-" : "", hdrbuf+6, fileinfo.st_size); + printf("Header CRC32: %.8x\n", hdr_crc); + printf("Data CRC32: %.8x\n", crc); + + bytes_written = write(fd_o, hdrbuf, HDR_SIZE); + if (bytes_written != HDR_SIZE) { + printf("Couldn't write output file\n"); + return -1; + } + + tot_bytes_read = 0; + lseek(fd_i, 0, SEEK_SET); + while ((bytes_read = read(fd_i, rdbuf, BUF_SIZE)) > 0) { + bytes_written = write(fd_o, rdbuf, bytes_read); + if (bytes_written != bytes_read) { + printf("Couldn't write output file\n"); + return -1; + } + tot_bytes_read += bytes_read; + } + + if (tot_bytes_read != fileinfo.st_size) { + printf("Incorrect size output file\n"); + return -1; + } + + printf("Firmware image written to %s\n", fw_bin_name); + + close(fd_o); + close(fd_i); + + return 0; +}