📄 drivers.asm
字号:
; MP3 Player, Device Drivers, http://www.pjrc.com/tech/mp3; Copyright (c) 2000, PJRC.COM, LLC; 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 2; 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, write to the Free Software; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.; As a specific exception to the GPL, the executable object code built; from this source code may be combined with hardware configuration data; files. A hardware configuration data file is a set of data that is; transmitted to an intergrated circuit that is not a general purpose; microprocessor or microcontroller, in order to establish its normal; operation. The process of combining the executable ojbect code built; from the GPL licensed source code with the hardware configuration data; shall be considered an aggregation of another work not based on the; Program. While the GPL does not restrict use of the program, any; use restriction associated with the hardware configuration data (for; example, that it only be used with particular hardware) shall apply; to the combined file which includes a copy of the hardware configuration; data.; Contact: paul@pjrc.com; drivers for MP3 player hardware. These drivers are loaded into; bank1 of the flash memory, and are intended to be called from a; program running in bank0..equ reg0, 0.equ reg1, 1.equ reg2, 2.equ reg3, 3.equ reg4, 4.equ reg5, 5.equ reg6, 6.equ reg7, 7.equ location, 0x3000 ;where this program will exist.equ params_storage, 0x8000.equ sta013_config_location, 0x9000.equ xilinx_bitstream_location, 0xD000.equ xilinx_alt_bitstream_location, 0xA000.equ return_addr, 0x0FF0 ;jump here to return to caller in bank0.equ rst_devices, 0x006A ;give a reset to the STA013, Xilinx, and Flash.equ scl_pin, 0x90.equ sda_pin, 0x91.equ hc165_load_pin, 0x94.equ xilinx_cclk_pin, 0x95.equ hc165_clk_pin, 0x95.equ hc165_data_pin, 0x96.equ xilinx_din_pin, 0x97.equ flash_a16_pin, 0xB4.equ shutdown_pin, 0xB5;*************************************************************;** **;** Memory Allocation **;** **;*************************************************************.equ max_attenuation, 64.equ default_attenuation, 12; we'll keep a 4k chunk of DRAM memory from 8000 to 8FFF.equ num_blks_played, 0x8004 ;2 bytes, number of blocks sent to STA013.equ last_fat_sector, 0x8006 ;4 bytes, remember which fat sector used last.equ last_fat_block, 0x800A ;2 bytes, remember which block it's in.equ last_fat_fd, 0x800C ;1 byte, remember which file desc also.equ mm_num_free, 0x800E ;2 bytes, number of free blocks.equ mm_free_list, 0x8014 ;2 bytes, first free block.equ mm_pending_free, 0x8016 ;2 bytes, xfer pending, waiting to be free; SPARE 8018 - 801D.equ mm_num_tracked, 0x801E ;2 bytes, number of blocks in mem tracker.equ clock_tick, 0x8020 ;4 bytes, clock inc at 10 Hz.equ dirrdf_addr, 0x8024 ;2 bytes, addr of filename.equ ide_retry_count, 0x8026 ;1 byte, # of times IDE command tried.equ root_dir_cluster, 0x8028 ;4 bytes.equ first_data_sector, 0x802C ;4 bytes.equ first_fat_sector, 0x8030 ;4 bytes.equ partition_first_sector, 0x8034 ;4 bytes.equ ide_current_req, 0x8038 ;8 bytes, current IDE read request.equ sw_timer, 0x8040 ;16 bytes, eight software timers.equ sw_timer_tick, 0x8050 ;1 byte.equ sw_timer_mask, 0x8051 ;1 byte, eight timer flags.equ sta013_silence, 0x8052 ;4 bytes, loc/len of silence to play when idle.equ event_queue, 0x80C0 ;64 bytes, 1 per event.equ event_queue_size, 64.equ rx_buffer, 0x8100 ;256 bytes, serial port receive buffer.equ tx_buffer, 0x8200 ;256 bytes, serial port transmit buffer.equ play_req, 0x8300 ;240 bytes, 60 play requests.equ play_req_size, 60.equ clust_read_req, 0x8400 ;960 bytes, 120 read requests.equ clust_rreq_size, 120;.equ unused_buf2, 0x8800 ;256 bytes.equ fat_read_req, 0x8900 ;192 bytes, 24 read requests.equ fat_rreq_size, 24.equ dont_ever_write, 0x89D2 ;1 byte, don't ever write here!!.equ file_info, 0x8A00 ;??? bytes (64 files, 24 bytes each); 8051 external address space usage;; 0000 to 5FFF Main Program, six pages of static memory; 6000 to 7FFF Main Program, two pages for dynamic memory; 8000 to 8FFF Drivers, static variables; 9000 to 9FFF STA013 device driver (DMA from here to the chip); A000 to AFFF IDE device driver (DMA into this area); B000 to BFFF FAT32, temporary use to read cached data; C000 to CFFF; D000 to DFFF FAT32, (static) list of blocks holding FAT sectors; E000 to EFFF Memory Manager; F000 to FEFF Not implemented; FF00 to FFFF DRAM, DMA, IDE control registers.equ auxr1, 0xA2 ;SFR to switch between dual DPTRs; functions built into Paulmon2... we can't call these anymore; because the current DRAM bus arbitrator isn't very smary and; it pauses DMA when the PSEN strobes stop, which occurs when; one of these functions waits to send/receive a character..equ cout, 0x2030.equ cin, 0x2032.equ pm2_cout, 0x0030 ;Send Acc to serial port;.equ cin, 0x0032 ;Get Acc from serial port.equ pm2_phex, 0x0034 ;Print Hex value of Acc;.equ phex1, 0x002E;.equ phex16, 0x0036 ;Print Hex value of DPTR.equ pm2_pstr, 0x0038 ;Print string pointed to by DPTR,;.equ upper, 0x0040 ;Convert Acc to uppercase;.equ pint8u, 0x004D ;print Acc at an integer, 0 to 255.equ pm2_pint8, 0x0050 ;print Acc at an integer, -128 to 127;.equ pint16u, 0x0053 ;print DPTR as an integer, 0 to 65535.equ pm2_newline, 0x0048 ;print CR/LF (13 and 10).equ prgm, 0x0059 ;program flash byte in A to @DPTR.equ erblock, 0x0067 ;PAULMON2 v2.1 req'd; registers implemented in the DRAM, IDE, and DMA controller.equ dram_page_cfg, 0xFF00.equ ide_data, 0xFF60.equ ide_err, 0xFF62.equ ide_sec_cnt, 0xFF64.equ ide_sector, 0xFF66.equ ide_cyl_lsb, 0xFF68.equ ide_cyl_msb, 0xFF6A.equ ide_head, 0xFF6C.equ ide_command, 0xFF6E.equ ide_status, 0xFF6E.equ ide_control, 0xFF7C.equ ide_astatus, 0xFF7C.equ ide_rst_bit, 0xFF40.equ ide_data_buf_msb, 0xFF43 ; caution, see notes on web site.equ dma_ide_dest, 0xFF22.equ dma_ide_count, 0xFF24.equ irq_dma_ide_ack,0xFF5C.equ dma_ide_go, 0xFF58.equ irq_ident, 0xFF50.equ irq_mask, 0xFF51.equ dma_mp3_src, 0xFF28.equ dma_mp3_count, 0xFF2A.equ dma_mp3_go, 0xFF59.equ irq_dma_mp3_ack,0xFF5D.equ irq_memcpy_ack, 0xFF5E;IDE Command Constants. These should never change..equ ide_cmd_recal, 0x10.equ ide_cmd_read, 0x20.equ ide_cmd_read_mult, 0xC4.equ ide_cmd_set_mult, 0xC6.equ ide_cmd_write, 0x30.equ ide_cmd_init, 0x91.equ ide_cmd_id, 0xEC.equ ide_cmd_spindown, 0xE0.equ ide_cmd_spinup, 0xE1.equ ide_cmd_idle, 0xE1.equ ide_cmd_sleep, 0xE6.equ ide_cmd_set_features, 0xEF.equ ide_cmd_initparms, 0x91.equ ide_cmd_nop, 0x00; internal 8051 memory allocation; don't use locations 0x00 to 0x07, they're needed for the registers; don't use locations 0x08 to 0x0F, they're used by interrupt routines.equ event_queue_head, 0x10 ;1 byte.equ event_queue_tail, 0x11 ;1 byte.equ button_state, 0x12 ;1 byte.equ dma_bug_temp, 0x13 ;1 byte.equ bsearch_tmp, 0x14 ;2 bytes.equ rx_buf_head, 0x16 ;1 byte.equ rx_buf_tail, 0x17 ;1 byte.equ fat_rreq_head, 0x18 ;1 byte.equ fat_rreq_tail, 0x19 ;1 byte.equ clust_rreq_head, 0x1A ;1 byte.equ clust_rreq_tail, 0x1B ;1 byte.equ ide_state, 0x1C ;1 byte.equ play_req_head, 0x1D ;1 byte.equ play_req_tail, 0x1E ;1 byte.equ blocks_per_cluster, 0x1F ;1 byte.equ reserved_bits_sdcc1, 0x20 ;1 byte, bits 0x00 - 0x07.equ reserved_bits_sdcc2, 0x21 ;1 byte, bits 0x08 - 0x0F.equ reserved_bits_sdcc3, 0x22 ;1 byte, bits 0x10 - 0x17.equ flags2, 0x23 ;1 byte, bits 0x18 - 0x1F.equ flags1, 0x24 ;1 byte, bits 0x20 - 0x27.equ master_slave, 0x25 ;1 byte, ide master/slave setting.equ dirrdf_lfn_count, 0x26; ;1 byte, # of short dir FAT entries found.equ tx_buf_head, 0x27 ;1 byte.equ tx_buf_tail, 0x28 ;1 byte.equ pb_count_v_up, 0x29 ;1 byte.equ pb_count_v_dn, 0x2A ;1 byte.equ cout_timeout, 0x2B ;1 byte.equ prev_cluster_at_block, 0x2C ;2 bytes.equ next_cluster_at_block, 0x2E ;2 bytes.equ cluster, 0x30 ;4 bytes.equ f32_sector, 0x34 ;4 bytes.equ cluster_offset, 0x38 ;3 bytes.equ sectors_per_cluster, 0x3B ;1 byte.equ ide_timeout_count, 0x3C ;1 byte.equ file_desc, 0x3D ;1 byte;SDCC's linker will start allocating DSEG variables at 0x40 !!; internal bit addressable memory allocation.equ fcw_is_waiting, 0x18.equ pb_state_next, 0x19.equ pb_state_play, 0x1A.equ pb_state_prev, 0x1B.equ pb_state_rand, 0x1C.equ tx_intr_expected, 0x1D.equ mute_is_on, 0x1E.equ debug, 0x1F.org location.db 0xA5,0xE5,0xE0,0xA5 ;signiture bytes.db 0,255,0,0 ;id.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;reserved.db 0,0,0,0 ;user defined.db 255,255,255,255 ;length and checksum (255=unused).db "Hardware Drivers",0.org location+64;entry table... call to 0x0FE0 (within PM2) with one of these;addresses in DPTR to call these drivers from bank0 ljmp xdownload ;64 download xilinx bitstream ljmp sta013_init ;67 initialize the sta013 ljmp shutdown ;70 shut off the power supply ljmp alt_xdownload ;73 download xilinx bitstream ljmp sta013_rd ;76 read from the sta013 ljmp sta013_wr ;79 write to the sta013 ljmp ide_hard_reset_c ;82 ljmp ide_init_c ;85 ljmp ide_flush_c ;88 ljmp do_ide_loop_c ;91 ljmp ide_sleep_c ;94 ljmp is_ide_sleeping_c ;97 ljmp is_ide_idle_c ;100 ljmp init_memory_mgr_c ;103 ljmp detect_simm_size_c ;106 ljmp print_memory_available ;109 ljmp 0 ;112 ljmp malloc_blocks_c ;115 ljmp free_blocks_c ;118 ljmp next_block_c ;121 ljmp play_block_c ;124 ljmp play_resume_c ;127 ljmp play_suspend_c ;130 ljmp play_abort_c ;133 ljmp play_queue_avail_c ;136 ljmp is_play_queue_empty_c ;139 nop ;142, unused (was sta013_get_attenuation) nop nop ljmp sta013_set_attenuation ;145 ljmp test_sta013_c ;148 ljmp detect_filesystem ;151 ljmp file_open_by_1st_cluster;154 ljmp file_cache ;157 ljmp file_cache_work ;160 ljmp file_seek ;163 ljmp file_read_c ;166 ljmp file_read_block ;169 ljmp file_close ;172 ljmp free_fat_memory ;175 nop ;178, unused (was original dir_read) nop nop ljmp update_events ;181 ljmp get_next_event ;184 ljmp put_back_event ;187 ljmp file_tell ;190 ljmp file_uncache ;193 ljmp write_flash_param ;196 ljmp read_param_1byte ;199 ljmp fill_null_mp3_c ;202 ljmp drivers_init ;205 ljmp play_dma_irq_enable ;208 ljmp get_root_1st_cluster ;211 ljmp set_timer ;214 ljmp read_timer ;217 ljmp clear_timer ;220 ljmp get_clock_tick ;223 ljmp sta013_read_header ;226 ljmp dir_read_fast ;229 ljmp dir_read_fast_name ;232 ljmp file_mem_map ;235 ;initialize critical stuff heredrivers_init: clr a mov ie, a ;all interrupts off until enabled mov ip, #00010000b ;uart higher priority, others all low .equ iph, 0xB7 mov iph, a ;don't use Philips special interrupt priorities mov flags1, a mov event_queue_head, a mov event_queue_tail, a acall read_buttons orl a, 0x10 mov button_state, a mov dptr, #sw_timer mov r0, #8 clr adinit2: movx @dptr, a inc dptr djnz r0, dinit2 mov dptr, #clock_tick mov r0, #4 clr adinit3: movx @dptr, a inc dptr djnz r0, dinit3 mov dptr, #sw_timer_tick movx @dptr, a mov dptr, #sw_timer_mask movx @dptr, a setb debug ;clr a ;mov r0, #state_next ;mov @r0, a ;mov r0, #state_prev ;mov @r0, a ;mov r0, #state_play ;mov @r0, a ;mov r0, #state_quit ;mov @r0, a ;mov r0, #state_debug ;mov @r0, a ;mov r0, #state_random ;mov @r0, a ;mov r0, #state_inc ;mov @r0, a ;mov r0, #state_dec ;mov @r0, a ;mov r0, #state_plnext ;mov @r0, a ;mov r0, #state_plprev ;;mov @r0, a ;mov r0, #state_up ;mov @r0, a ;mov r0, #state_down ;mov @r0, a ;mov r0, #state_left ;mov @r0, a ;mov r0, #state_right ;mov @r0, a ;mov r0, #state_enter ;mov @r0, a ;mov r0, #state_fwd ;mov @r0, a ;mov r0, #state_rev ;mov @r0, a ljmp return_addrset_timer: mov a, r4 add a, #(0x100 - 8) ;check < 8 jc set_timer_end setb c ;determine mask clr a mov r1, reg4 inc r1set_timer_shift: rlc a djnz r1, set_timer_shift mov b, a mov dptr, #sw_timer ;find count location mov a, r4 rl a add a, dpl mov dpl, a mov a, r2 clr ea movx @dptr, a ;store timer duration inc dptr mov a, r3 movx @dptr, a mov dptr, #sw_timer_mask movx a, @dptr ;enable timer orl a, b movx @dptr, a setb easet_timer_end: ljmp return_addrread_timer: mov a, r4 add a, #(0x100 - 8) ;check < 8 jc read_timer_end mov a, r4 rl a add a, #sw_timer & 255 mov dpl, a mov dph, #sw_timer >> 8 clr ea movx a, @dptr inc dptr mov r3, a movx a, @dptr setb ea mov dpl, r3 mov dph, aread_timer_end: ljmp return_addrclear_timer: mov a, r4 add a, #(0x100 - 8) ;check < 8 jc clear_timer_end setb c ;determine mask clr a mov r1, reg4 inc r1clear_timer0: rlc a djnz r1, clear_timer0 xrl a, #0xff ;turn into mask mov b, a mov dptr, #sw_timer_mask setb ea movx a, @dptr ;disable timer anl a, b movx @dptr, a clr ea mov dptr, #sw_timer ;find count location mov a, r4 rl a add a, dpl mov dpl, a clr a clr ea movx @dptr, a ;clear timer duration inc dptr movx @dptr, a setb eaclear_timer_end: ljmp return_addrget_clock_tick: mov dptr, #clock_tick clr ea movx a, @dptr inc dptr mov r0, a movx a, @dptr inc dptr mov r1, a movx a, @dptr inc dptr mov b, a movx a, @dptr setb ea mov dph, r1 mov dpl, r0 ljmp return_addr ;download a bitstream to the xilinx chip. ;return DPL=0 if ok, DPL=1 if an errorxdownload: mov dptr, #xilinx_bitstream_location - 1 acall get_next_byte cjne a, #0xFF, no_bitstream ;fill byte acall get_next_byte cjne a, #0x04, no_bitstream ;preamble, upper 4 bits of length acall get_next_byte cjne a, #0xE8, no_bitstream ;next 8 bits of length ; Foundation 3.3sp8 changed the bitstream length! ; acall get_next_byte ; cjne a, #0xFA, no_bitstream ;next 8 bits of length ; acall get_next_byte ; cjne a, #0xF9, no_bitstream ;lower 4 bits length, fill bits ;reset the xilinx chip... also resets the STA013 and flash lcall rst_devices ;wait for 3ms for the xilinx chip to be ready ;at 7.3728 MHz / 12, that's 1843 instruction cycles djnz r0, * ;512 cycles djnz r0, * ;512 cycles djnz r0, * ;512 cycles mov r0, #153 ;1 cycle djnz r0, * ;306 cycles setb xilinx_din_pin setb xilinx_cclk_pin mov dptr, #xilinx_bitstream_locationxd_loop1: clr a movc a, @a+dptr inc dptr rrc a mov xilinx_din_pin, c clr xilinx_cclk_pin setb xilinx_cclk_pin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -