1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-02-04 07:12:56 +08:00

1616 lines
90 KiB
Plaintext

;KCPSM3 Program - UART programming of StrataFLASH memory on the Spartan-3E Starter Kit.
;
;Ken Chapman - Xilinx Ltd
;
;Version v1.00 - 28th March 2006
;
;This program uses a 115200 baud UART connection with XON/XOFF flow control
;to allow a standard MCS file for the configuration of a Spartan-3E device to
;be programmed into the Intel StrataFLASH device on the board.
;
;
;
;
;**************************************************************************************
; Port definitions
;**************************************************************************************
;
;
CONSTANT status_port, 00 ;UART and filter status input
CONSTANT tx_data_present, 01 ; Transmitter data present - bit0
CONSTANT tx_half_full, 02 ; FIFO half full - bit1
CONSTANT tx_full, 04 ; full - bit2
CONSTANT rx_data_present, 08 ; data present - bit3
CONSTANT rx_half_full, 10 ; Receiver half full - bit4
CONSTANT rx_full, 20 ; FIFO full - bit5
CONSTANT spare1, 40 ; spare '0' - bit6
CONSTANT SF_STS, 80 ; StrataFLASH STS - bit7
;
CONSTANT UART_read_port, 01 ;UART Rx data input
;
CONSTANT UART_write_port, 04 ;UART Tx data output
;
;
CONSTANT SF_data_in_port, 02 ;Read data from StrataFLASH device
;
CONSTANT SF_data_out_port, 10 ;Data to write into StrataFLASH device
;
CONSTANT SF_addr_hi_port, 80 ;StrataFLASH address[23:16]
CONSTANT SF_addr_mi_port, 40 ;StrataFLASH address[15:8]
CONSTANT SF_addr_lo_port, 20 ;StrataFLASH address[7:0]
;
CONSTANT SF_control_port, 08 ;StrataFLASH control
CONSTANT SF_read, 01 ; active High read - bit0
CONSTANT SF_ce, 02 ; active Low device enable - bit1
CONSTANT SF_we, 04 ; active Low write - bit2
;
;
;
;**************************************************************************************
; Special Register usage
;**************************************************************************************
;
NAMEREG sF, UART_data ;used to pass data to and from the UART
;
;
;**************************************************************************************
; Useful data constants
;**************************************************************************************
;
;Constant to define a software delay of 1us. This must be adjusted to reflect the
;clock applied to KCPSM3. Every instruction executes in 2 clock cycles making the
;calculation highly predictable. The '6' in the following equation even allows for
;'CALL delay_1us' instruction in the initiating code.
;
; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
;
;Example: For a 50MHz clock the constant value is (10-6)/4 = 11 (0B Hex).
;For clock rates below 10MHz the value of 1 must be used and the operation will
;become lower than intended.
;
CONSTANT delay_1us_constant, 0B
;
;
;
;ASCII table
;
CONSTANT character_a, 61
CONSTANT character_b, 62
CONSTANT character_c, 63
CONSTANT character_d, 64
CONSTANT character_e, 65
CONSTANT character_f, 66
CONSTANT character_g, 67
CONSTANT character_h, 68
CONSTANT character_i, 69
CONSTANT character_j, 6A
CONSTANT character_k, 6B
CONSTANT character_l, 6C
CONSTANT character_m, 6D
CONSTANT character_n, 6E
CONSTANT character_o, 6F
CONSTANT character_p, 70
CONSTANT character_q, 71
CONSTANT character_r, 72
CONSTANT character_s, 73
CONSTANT character_t, 74
CONSTANT character_u, 75
CONSTANT character_v, 76
CONSTANT character_w, 77
CONSTANT character_x, 78
CONSTANT character_y, 79
CONSTANT character_z, 7A
CONSTANT character_A, 41
CONSTANT character_B, 42
CONSTANT character_C, 43
CONSTANT character_D, 44
CONSTANT character_E, 45
CONSTANT character_F, 46
CONSTANT character_G, 47
CONSTANT character_H, 48
CONSTANT character_I, 49
CONSTANT character_J, 4A
CONSTANT character_K, 4B
CONSTANT character_L, 4C
CONSTANT character_M, 4D
CONSTANT character_N, 4E
CONSTANT character_O, 4F
CONSTANT character_P, 50
CONSTANT character_Q, 51
CONSTANT character_R, 52
CONSTANT character_S, 53
CONSTANT character_T, 54
CONSTANT character_U, 55
CONSTANT character_V, 56
CONSTANT character_W, 57
CONSTANT character_X, 58
CONSTANT character_Y, 59
CONSTANT character_Z, 5A
CONSTANT character_0, 30
CONSTANT character_1, 31
CONSTANT character_2, 32
CONSTANT character_3, 33
CONSTANT character_4, 34
CONSTANT character_5, 35
CONSTANT character_6, 36
CONSTANT character_7, 37
CONSTANT character_8, 38
CONSTANT character_9, 39
CONSTANT character_colon, 3A
CONSTANT character_fullstop, 2E
CONSTANT character_semi_colon, 3B
CONSTANT character_minus, 2D
CONSTANT character_plus, 2B
CONSTANT character_comma, 2C
CONSTANT character_less_than, 3C ;'<'
CONSTANT character_greater_than, 3E ;'>'
CONSTANT character_open, 28 ;'('
CONSTANT character_close, 29 ;')'
CONSTANT character_divide, 2F ;'/'
CONSTANT character_equals, 3D
CONSTANT character_space, 20
CONSTANT character_CR, 0D ;carriage return
CONSTANT character_LF, 0A ;line feed
CONSTANT character_question, 3F ;'?'
CONSTANT character_dollar, 24
CONSTANT character_exclaim, 21 ;'!'
CONSTANT character_BS, 08 ;Back Space command character
CONSTANT character_XON, 11 ;Flow control ON
CONSTANT character_XOFF, 13 ;Flow control OFF
;
;
;**************************************************************************************
; Scratch Pad Memory Locations
;**************************************************************************************
;
CONSTANT ISR_preserve_s0, 00 ;preserve register during ISR
;
;
;
;Store up to one line of an MCS file as bytes
;A typical data line consists of:-
;: Start character which is not stored
;10 Number of data bytes included (16 in this case)
;aaaa Lower 16-bits of the storage address
;00 Record type (data in this case)
;dddd... Data bytes (typically 16 which is the maximum)
;cc Checksum
;CR/LF Line will end in carriage return and/or line feed which is not stored.
;
;So a total of 21 bytes could be stored before processing.
;This is located at the end of scratch pad memory.
;
CONSTANT line_start, 2B ;21 bytes until end of memory
CONSTANT data_start, 2F ;Start of data field if present
;
;
;**************************************************************************************
; Initialise the system and welcome message
;**************************************************************************************
;
cold_start: CALL SF_init ;initialise StrataFLASH controls
CALL delay_1s ;delay because UART is fast and JTAG startup sequence can be slow
ENABLE INTERRUPT ;Interrupt is used for XON/XOFF flow control
welcome_start: CALL send_CR
CALL send_welcome ;start up message and version number
;
;
;**************************************************************************************
; Main menu and command selection
;**************************************************************************************
;
;
warm_start: CALL send_Menu ;Menu and command selection
CALL send_CR
;
prompt: CALL send_CR
CALL send_CR
LOAD UART_data, character_greater_than ;prompt for input
CALL send_to_UART
CALL read_upper_case
COMPARE s0, character_E ;test for commands and execute as required
JUMP Z, erase_command
COMPARE s0, character_B
JUMP Z, block_erase_command
COMPARE s0, character_P
JUMP Z, program_command
COMPARE s0, character_W
JUMP Z, write_command
COMPARE s0, character_R
JUMP Z, read_command
COMPARE s0, character_I
JUMP Z, SF_information
COMPARE s0, character_H
JUMP Z, welcome_start
COMPARE s0, character_S
JUMP Z, SF_status
CALL send_CR ;no valid command input
LOAD UART_data, character_question ;display ???
CALL send_to_UART
CALL send_to_UART
CALL send_to_UART
JUMP prompt ;Try again!
;
;
read_upper_case: CALL read_from_UART ;read command character from UART
CALL send_to_UART ;echo character
LOAD s0, UART_data ;convert to upper case
CALL upper_case
RETURN
;
;
;**************************************************************************************
; Initialise the StrataFlash Memory control signals.
;**************************************************************************************
;
; SF_read = 0 - Output enable off
; SF_ce = 1 - Deselect StrataFLASH memory
; SF_we = 1 - Write enable off
;
; Register used s0
;
SF_init: LOAD s0, 06
OUTPUT s0, SF_control_port
RETURN
;
;
;**************************************************************************************
; Erase Command - Perform bulk erase of the StrataFLASH memory
;**************************************************************************************
;
; This routine executes the block erase command 128 times with a different base
; address in each case.
;
; Note that this could take as long as 8 minutes 30 seconds
; and even typical times will be approximately 2 minutes.
;
; Registers used s1,s7,s8,s9
;
erase_command: LOAD s9, FE ;define base address of block 127 = FE0000
JUMP blocks_erase
;
;
;**************************************************************************************
; Block Erase Command - Performs erase of lowest 3 blocks of StrataFLASH memory which
; covers the address range 000000 to 05FFFF in which the configuration for an XC3S500E
; would be able to fit (000000 to 045470).
;**************************************************************************************
;
; This routine executes the block erase command 3 times with a different base
; address in each case.
;
; Each block is 128K bytes and therefore has an address range of 000000 to 01FFFF.
; So each block is separated by 020000 hex.
;
; Registers used s0,s1,s7,s8,s9
;
block_erase_command: LOAD s9, 04 ;define base address of block 3 = 040000
blocks_erase: CALL send_CR
CALL send_Confirm ;confirm command with a 'Y' which must be upper case
CALL read_from_UART ;read command character from UART
CALL send_to_UART ;echo input
COMPARE UART_data, character_Y
JUMP NZ, abort_erase
CALL send_CR
CALL send_Erase_in_progress
CALL send_CR
LOAD s8, 00 ;define lower address of each block = xx0000
LOAD s7, 00
blocks_erase_loop: LOAD UART_data, character_fullstop ;progress dots
CALL send_to_UART
CALL SF_erase_block ;erase block
SUB s9, 02 ;decrement base address by 1 block
JUMP NC, blocks_erase_loop ;repeat until block 0 is erased
CALL send_OK
JUMP prompt
;
abort_erase: CALL send_Abort
JUMP prompt
;
;
;**************************************************************************************
; Erase a single 128K Byte block of the StrataFlash Memory
;**************************************************************************************
;
; The 24-bit address of the block should be supplied in register set [s9,s8,s7].
;
; To erase a block the address must be set and then the block erase command (20 hex)
; written to the memory followed by the write confirm command (D0 hex).
;
; The act of erasing a block may take up to 1 second to complete. This routine
; waits for the memory to be ready before restoring the normal read array mode and
; returning.
;
; Registers used s1,s7,s8,s9
;
SF_erase_block: LOAD s1, 20 ;block erase command
CALL SF_byte_write
LOAD s1, D0 ;write confirm command
CALL SF_byte_write
CALL wait_SF_ready ;wait for erase to complete
RETURN
;
;
;**************************************************************************************
; Program Command - Program StrataFLASH memory with data defined in an MCS file
;**************************************************************************************
;
program_command: CALL send_CR
CALL send_Waiting_MCS_file
CALL program_MCS
CALL send_OK
JUMP prompt
;
;**************************************************************************************
; Program StrataFLASH memory with data defined in an MCS file
;**************************************************************************************
;
;Reads the MCS file from the UART and programs the Strata FLASH device at the locations.
;specified by the file contents.
;
;This routine will continue until an end of file record is detected.
;For each line of MCS received, the current address will be output so that
;progress can be monitored.
;
;
program_MCS: CALL read_MCS_line ;read line from UART
CALL MCS_address ;find start address and record type
COMPARE sB, 01 ;test for end record
RETURN Z ;end of programming
COMPARE sB, 04 ;test for extended address record
JUMP Z, program_MCS ;no data with this record and upper address now correct
;
;Assume data record type 00 which is data so need to program specified number
;of bytes into memory at correct address.
;
write_spm_data: CALL send_hex_3bytes ;send address to indicate progress
CALL send_CR
FETCH sA, line_start ;read number of data bytes to program
CALL SF_buffer_write ;write bytes to memory
JUMP program_MCS
;
;
;**************************************************************************************
;Read one line of an MCS file into scratch pad memory
;**************************************************************************************
;
;Reads one line of MCS file format into scratch pad memory starting at location 'line_start'.
;
;The routine detects the line start character ':' ignoring any preceding characters. This
;will remove any additional CR or LF characters.
;
;It then reads each subsequent pair of ASCII characters, converts them to true hex in the
;range 00 to FF and stores them in scratch pad memory.
;
;The end of the line is determined by either a CR or LF character.
;
;The value last returned in register 'sE' will be the pointer to the location in
;scratch pad memory following the last byte for the line read.
;
read_MCS_line: LOAD sE, line_start ;initialise SPM memory pointer
wait_MCS_line_Start: CALL read_from_UART ;read character
COMPARE UART_data, character_colon ;test for start character
JUMP NZ, wait_MCS_line_Start
read_MCS_byte: CALL read_from_UART ;read character
COMPARE UART_data, character_CR ;test for end of line
RETURN Z
COMPARE UART_data, character_LF ;test for end of line
RETURN Z
LOAD s3, UART_data ;upper nibble character
CALL read_from_UART ;read character
LOAD s2, UART_data ;lower nibble character
CALL ASCII_byte_to_hex ;convert to true hex value
STORE s0, (sE) ;write to SPM
ADD sE, 01 ;increment pointer
JUMP read_MCS_byte
;
;
;**************************************************************************************
;Determine the current address for the line of an MCS file in scratch pad memory
;**************************************************************************************
;
;Checks the existing line data stored in scratch pad memory starting at location
;'line_start' and determines the current address.
;
;The address is in the register set [s9,s8,s7] before and after this routine is
;executed because not all address bits are defined by a given line of MCS and
;the undefined bits remain constant.
;
;A record type of 04 will update [s9].
;A record type of 00 will update [s8,s7].
;
;On return, the register sB will contain the record type and
;register sC will indicate the number of data bytes stored.
;
MCS_address: LOAD sD, line_start ;initialise SPM memory pointer
FETCH sC, (sD) ;read number of bytes on line
ADD sD, 03 ;move to record type
FETCH sB, (sD) ;read record type
COMPARE sB, 00 ;test for data record
JUMP Z, new_low_address
COMPARE sB, 04 ;test for data record
RETURN NZ
ADD sD, 02 ;read upper 8-bits
FETCH s9, (sD)
RETURN
new_low_address: SUB sD, 01 ;read lower 8-bits
FETCH s7, (sD)
SUB sD, 01 ;read middle 8-bits
FETCH s8, (sD)
RETURN
;
;
;**************************************************************************************
; Write to Buffer of StrataFlash Memory and program
;**************************************************************************************
;
; Writing to the buffer allows faster operation than writing individual bytes.
; The buffer size is limited to 32 locations. To perform a buffer write the process
; is as follows:-
; Write command for buffer write to StrataFLASH memory (E8 hex).
; Base address for writing should also be set.
; Read Status register and if not ready repeat command until it is.
; Write a value specifying the number of bytes to be written LESS ONE.
; In this program the number of bytes will be specified in register sA
; and this value needs to be decremented before writing to the memory.
; Write the correct number of actual data bytes with appropriate addresses.
; Ideally the addresses do not cross the boundary of 32 locations
; such that LSBs are always in the range 00000 to 11111 binary.
; Crossing the boundary is OK but will take longer to program.
; Write command to confirm operation (D0 hex).
; Read Status register and wait for ready.
;
; This routine additionally restores the normal read array mode before returning.
;
; The number of bytes to be written should be supplied in register sA and must be
; a value between 1 and 32 (01 and 20 hex).
;
; The 24-bit base address should be supplied in register set [s9,s8,s7].
; On return, this will be increased by the number of locations written.
;
; Scratch pad memory locations starting at location defined by constant
; 'data_start' should contain the data bytes to be written.
;
; The act of writing the buffer to the memory array may take up to 654us to complete.
; The time taken to program is recorded by register pair [sE,sD]. Each count
; equates to 15 instructions which is equivalent to 30 clock cycles (600ns at 50MHz).
;
; Registers used s0,s1,s7,s8,s9,sA,sD,sE
;
;
SF_buffer_write: LOAD s1, E8 ;command for buffer write
CALL SF_byte_write
CALL SF_byte_read ;read status register into s0
TEST s0, 80 ;test ready/busy flag
JUMP Z, SF_buffer_write ;repeat command until ready
LOAD s1, sA ;Specify number of bytes to write
SUB s1, 01 ;one less than actual number!
CALL SF_byte_write
LOAD s3, data_start ;point to data in scratch pad memory
write_buffer_loop: FETCH s1, (s3) ;fetch data
CALL SF_byte_write ;write to buffer
ADD s7, 01 ;increment address
ADDCY s8, 00
ADDCY s9, 00
ADD s3, 01 ;increment SPM pointer
SUB sA, 01 ;count bytes remaining
JUMP NZ, write_buffer_loop
LOAD s1, D0 ;command to confirm write
CALL SF_byte_write
CALL wait_SF_ready ;wait for program to complete and set read array mode
RETURN
;
;
;**************************************************************************************
; Write Command - Write one byte to specified address
;**************************************************************************************
;
write_command: CALL send_address ;obtain 24-bit address 000000 to FFFFFF
CALL obtain_8bits
JUMP C, write_command ;bad input address
LOAD s9, s0
CALL obtain_8bits
JUMP C, write_command ;bad input address
LOAD s8, s0
CALL obtain_8bits
JUMP C, write_command ;bad input address
LOAD s7, s0
get_data: CALL send_data ;obtain 8-bit data 00 to FF into s0
CALL obtain_8bits
JUMP C, get_data ;bad input data
CALL SF_single_byte_write
CALL send_CR
CALL send_OK
JUMP prompt
;
;
;**************************************************************************************
; Write a single byte to StrataFlash Memory
;**************************************************************************************
;
; To write a single byte to StrataFLASH memory the address must be set and the
; single-word/byte program command (40 hex) sent to the memory. Then the data byte can
; be written to the memory using the same address.
;
; The 24-bit address should be supplied in register set [s9,s8,s7].
; Register s0 should contain the byte data to be written to the memory.
;
; The act of writing the memory array may take up to 175us to complete. This routine
; waits for the memory to be ready before restoring the normal read array mode and
; returning. The time taken to program is recorded by register pair [sE,sD]. Each count
; equates to 15 instructions which is equivalent to 30 clock cycles (600ns at 50MHz).
;
; Registers used s0,s1,s7,s8,s9,sD,sE (s7,s8,s9 not changed)
;
; Registers used s0,s1,s7,s8,s9
;
SF_single_byte_write: LOAD s1, 40 ;command for single byte program
CALL SF_byte_write
LOAD s1, s0 ;write data to be programmed
CALL SF_byte_write
CALL wait_SF_ready ;wait for program to complete
RETURN
;
;
;**************************************************************************************
;Read Command - Read one page of memory at specified address
;**************************************************************************************
;
read_command: CALL send_address ;obtain 24-bit address 000000 to FFFFFF
CALL obtain_8bits ;read value from UART
JUMP C, read_command ;bad input address
LOAD s9, s0
CALL obtain_8bits
JUMP C, read_command ;bad input address
LOAD s8, s0
CALL obtain_8bits
JUMP C, read_command ;bad input address
LOAD s7, s0
CALL send_CR
CALL send_SF_page
CALL send_OK
JUMP prompt
;
;The start address should be provided in register set [s9,s8,s7].
;The display will be next 256 bytes displayed as 16 lines of 16 bytes
;with each line commencing with the address of the first byte.
;
send_SF_page: LOAD s6, 10 ;16 lines to display
send_SF_line: CALL send_CR
CALL send_hex_3bytes ;display address
CALL send_space
LOAD s5, 10 ;16 bytes to display on a line
send_SF_byte: CALL send_space
CALL SF_byte_read ;read byte into s0
ADD s7, 01 ;increment StrataFLASH address
ADDCY s8, 00
ADDCY s9, 00
CALL send_hex_byte ;display byte
SUB s5, 01 ;count bytes per line
JUMP NZ, send_SF_byte
SUB s6, 01 ;count lines
JUMP NZ, send_SF_line
CALL send_CR
RETURN
;
;
;**************************************************************************************
; ID Command - Read and display the device information for the StrataFLASH FLASH memory
;**************************************************************************************
;
; Normal response should be
; Device Manufacturer Code (Intel) = 89 hex
; Memory ID code for 128Mbit = 18 hex
;
; To read the device information the Read device information command (90)
; must be written to the memory. The information is read back but assumes
; that 16-bit words are being used and hence address bit0 is not really used.
; hence addresses 000000 and 0000001 both return the Device Manufacturer Code and
; addresses 000002 and 0000003 both return the Memory ID code.
;
; After reading the device information the read array command is written to the
; device to put it back to normal read mode.
;
; Registers used s0,s7,s8,s9
;
SF_information: CALL send_CR ;send 'ID=' to terminal
CALL send_ID
LOAD UART_data, character_equals
CALL send_to_UART
CALL send_space
LOAD s9, 00 ;define base address 000000
LOAD s8, 00
LOAD s7, 00
LOAD s1, 90 ;command to read device information
CALL SF_byte_write
CALL SF_byte_read ;read Device Manufacturer Code into s0
CALL send_hex_byte ;display byte
CALL send_space
LOAD s7, 02 ;change address
CALL SF_byte_read ;read Memory ID code into s0
CALL send_hex_byte ;display byte
CALL send_CR
CALL set_SF_read_array_mode ;restore normal read array mode
JUMP prompt
;
;
;**************************************************************************************
; Read StrataFLASH status register
;**************************************************************************************
;
; The main reason for reading the status register is to determine when the memory
; is ready or busy. This information is provided by bit7 (0=busy and 1=ready).
;
; The lower bits all indicate errors of some kind and therefore the only desirable
; response is 00 hex or 80 hex. In this program, no error checking or clearing
; is performed and the way this routine is executed from the menu only 80 hex is
; expected.
;
; To read the status register the read status register command must be written to
; the device. All subsequent reads are then result in the return of the status
; register. A different read command must be written to the device to stop this
; mode.
;
; This mode is also entered automatically when performing program and erase operations.
;
SF_status: LOAD s9, 00 ;define base address 000000
LOAD s8, 00
LOAD s7, 00
LOAD s1, 70 ;command to read status register
CALL SF_byte_write
CALL send_CR
CALL SF_byte_read ;read status register into s0
CALL send_hex_byte ;display byte
CALL send_CR
CALL set_SF_read_array_mode
JUMP prompt
;
;
;**************************************************************************************
; Read a byte from StrataFlash Memory
;**************************************************************************************
;
; The 24-bit address should be supplied in register set [s9,s8,s7].
; Register s0 will return the byte data retrieved from the memory.
;
; To read a byte, the address needs to be set up on the address lines
; and the controls set as follows
; SF_read = 1 - disable Spartan data outputs and enable StrataFlash outputs (OE=0)
; SF_ce = 0 - enable StrataFLASH memory
; SF_we = 1 - Write enable off
;
; The access time of the memory is 75ns. This is equivalent to 3.75 clock cycles at
; 50MHz. Since each KCPSM3 instruction takes 2 clock cycles to execute, two instructions
; provides adequate delay for the memory to be accessed.
;
; Registers used s0,s1,s7,s8,s9
;
SF_byte_read: OUTPUT s9, SF_addr_hi_port ;set 24-bit address
OUTPUT s8, SF_addr_mi_port
OUTPUT s7, SF_addr_lo_port
LOAD s1, 05 ;set controls
OUTPUT s1, SF_control_port
LOAD s1, 06 ;>75ns delay
LOAD s1, 06 ;but do something useful!
INPUT s0, SF_data_in_port ;read data byte
OUTPUT s1, SF_control_port ;clear controls
RETURN
;
;
;**************************************************************************************
; Write data or command byte to StrataFlash Memory
;**************************************************************************************
;
; The 24-bit address should be supplied in register set [s9,s8,s7].
; Register s1 should contain the byte to be written to the memory.
;
; To write a byte, the address needs to be set up on the address lines
; and the controls set as follows
; SF_read = 0 - enable Spartan data outputs and disable StrataFlash outputs (OE=1)
; SF_ce = 0 - enable StrataFLASH memory
; SF_we = 0 - Write enable on
;
; The setup time of the memory is 60ns. This is equivalent to 3 clock cycles at
; 50MHz. Since each KCPSM3 instruction takes 2 clock cycles to execute, two instructions
; provides adequate delay for the memory.
;
; Registers used s1,s7,s8,s9
;
SF_byte_write: OUTPUT s9, SF_addr_hi_port ;set 24-bit address
OUTPUT s8, SF_addr_mi_port
OUTPUT s7, SF_addr_lo_port
OUTPUT s1, SF_data_out_port ;set data byte to be written
LOAD s1, 00 ;set controls
OUTPUT s1, SF_control_port
LOAD s1, 06 ;>60ns delay
LOAD s1, 06 ;but do something useful!
OUTPUT s1, SF_control_port ;clear controls
RETURN
;
;
;**************************************************************************************
; Set 'Read Array' mode on StrataFLASH
;**************************************************************************************
;
; The read array mode is the default mode of the memory and allows the contents
; of the memory to be read based on the supplied address.
;
; Read array is the default mode of the device, but it must also be placed back
; into this mode after programming, erasing or reading the status register.
;
; The read array command (FF hex) is written to the Strata flash memory.
;
; Registers used s1,s7,s8,s9
;
set_SF_read_array_mode: LOAD s1, FF ;command to read array
CALL SF_byte_write
RETURN
;
;
;**************************************************************************************
; Wait for StrataFLASH to be ready
;**************************************************************************************
;
; This routine will typically be used after instigating a program or erase
; command. It continuously reads the StrataFLASH status register and tests the
; information provided by bit7 which indicates if the memory is busy(0) or ready(1).
; The routine waits for the ready condition before sending a read array command
; which puts the memory back to normal read mode.
;
; During the polling process, a counter formed by register pair [sE,sD] records
; approximately how long the memory is busy. This can be used to evaluate programming
; and erase times if required. The timing loop is 15 instructions which is equivalent
; to 30 clock cycles (600ns at 50MHz)
;
; Registers used s0,s1,s7,s8,s9,sD,sE (s7,s8,s9 not changed)
;
;
wait_SF_ready: LOAD sE, 00 ;clear 16-bit counter timer
LOAD sD, 00
wait_SF_loop: ADD sD, 01 ;increment counter timer
ADDCY sE, 00
CALL SF_byte_read ;read status register into s0
TEST s0, 80 ;test ready/busy flag
JUMP Z, wait_SF_loop
CALL set_SF_read_array_mode ;restore normal read array mode
RETURN
;
;
;**************************************************************************************
; Send 16-bit value in register pair [sE,sD] to UART
;**************************************************************************************
;
; In this program the register pair [sE,sD] indicates the programming time of the
; StrataFLASH memory in 600ns increments. This routine can be used to display that
; value if required.
;
send_counter_timer: CALL send_CR
LOAD s0, sE
CALL send_hex_byte
LOAD s0, sD
CALL send_hex_byte
CALL send_CR
RETURN
;
;
;**************************************************************************************
;Software delay routines
;**************************************************************************************
;
;Delay of 1us.
;
;Constant value defines reflects the clock applied to KCPSM3. Every instruction
;executes in 2 clock cycles making the calculation highly predictable. The '6' in
;the following equation even allows for 'CALL delay_1us' instruction in the initiating code.
;
; delay_1us_constant = (clock_rate - 6)/4 Where 'clock_rate' is in MHz
;
;Registers used s0
;
delay_1us: LOAD s0, delay_1us_constant
wait_1us: SUB s0, 01
JUMP NZ, wait_1us
RETURN
;
;Delay of 40us.
;
;Registers used s0, s1
;
delay_40us: LOAD s1, 28 ;40 x 1us = 40us
wait_40us: CALL delay_1us
SUB s1, 01
JUMP NZ, wait_40us
RETURN
;
;
;Delay of 1ms.
;
;Registers used s0, s1, s2
;
delay_1ms: LOAD s2, 19 ;25 x 40us = 1ms
wait_1ms: CALL delay_40us
SUB s2, 01
JUMP NZ, wait_1ms
RETURN
;
;Delay of 20ms.
;
;Delay of 20ms used during initialisation.
;
;Registers used s0, s1, s2, s3
;
delay_20ms: LOAD s3, 14 ;20 x 1ms = 20ms
wait_20ms: CALL delay_1ms
SUB s3, 01
JUMP NZ, wait_20ms
RETURN
;
;Delay of approximately 1 second.
;
;Registers used s0, s1, s2, s3, s4
;
delay_1s: LOAD s4, 14 ;50 x 20ms = 1000ms
wait_1s: CALL delay_20ms
SUB s4, 01
JUMP NZ, wait_1s
RETURN
;
;
;**************************************************************************************
;UART communication routines
;**************************************************************************************
;
;Read one character from the UART
;
;Character read will be returned in a register called 'UART_data'.
;
;The routine first tests the receiver FIFO buffer to see if data is present.
;If the FIFO is empty, the routine waits until there is a character to read.
;As this could take any amount of time the wait loop could include a call to a
;subroutine which performs a useful function.
;
;If the received character is an XOFF, then the routine will then wait
;for an XON to be received. This means that the rest of the program is held
;in suspense and therefore it can not transmit. Once an XON is received, it will
;again wait for a normal character before returning.
;
;NOTE: Characters between the XOFF and XON will be ignored in this version of the
;program!!!
;
;Interrupt is disabled during this routine to prevent a false situation. If the
;receiver half-full flag went High it should result in an interrupt transmitting
;an XOFF character. However, if this routine were able to read the receiver buffer
;at just about the same as the hardware detects the half-full flag, then it could
;think that an XON needs to be transmitted.
;
;
;Registers used s0 and UART_data
;
read_from_UART: DISABLE INTERRUPT
wait_Rx_character: INPUT s0, status_port ;test Rx_FIFO buffer
TEST s0, rx_data_present
JUMP NZ, read_character
JUMP wait_Rx_character
read_character: INPUT UART_data, UART_read_port ;read from FIFO
COMPARE UART_data, character_XOFF ;test for XOFF
JUMP Z, wait_XON
ENABLE INTERRUPT ;normal finish
RETURN
wait_XON: INPUT s0, status_port ;test Rx_FIFO buffer
TEST s0, rx_data_present
JUMP NZ, read_XON
JUMP wait_XON
read_XON: INPUT UART_data, UART_read_port ;read from FIFO
COMPARE UART_data, character_XON ;test for XON
JUMP Z, wait_Rx_character ;now wait for normal character
JUMP wait_XON ;continue to wait for XON
;
;
;
;Transmit one character to the UART
;
;Character supplied in register called 'UART_data'.
;
;The routine first tests the transmit FIFO buffer is empty.
;If the FIFO currently has any data, the routine waits until it is empty.
;Ultimately this means that only one character is sent at a time which
;could be important if the PC at the other end of the link transmits
;an XOFF and needs the flow of data to terminate as soon as possible.
;
;Registers used s0
;
send_to_UART: INPUT s0, status_port ;test Tx_FIFO buffer
TEST s0, tx_data_present
JUMP Z, UART_write
JUMP send_to_UART
UART_write: OUTPUT UART_data, UART_write_port
RETURN
;
;
;**************************************************************************************
;Useful ASCII conversion and handling routines
;**************************************************************************************
;
;Convert value provided in register s0 into ASCII characters
;
;The value provided must in the range 0 to 99 and will be converted into
;two ASCII characters.
; The number of 'tens' will be represented by an ASCII character returned in register s1.
; The number of 'units' will be represented by an ASCII character returned in register s0.
;
;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex added to
;the actual decimal value.
;
;Registers used s0 and s1.
;
decimal_to_ASCII: LOAD s1, 30 ;load 'tens' counter with ASCII for '0'
test_for_ten: ADD s1, 01 ;increment 'tens' value
SUB s0, 0A ;try to subtract 10 from the supplied value
JUMP NC, test_for_ten ;repeat if subtraction was possible without underflow.
SUB s1, 01 ;'tens' value one less ten due to underflow
ADD s0, 3A ;restore units value (the remainder) and convert to ASCII
RETURN
;
;
;
;Convert character to upper case
;
;The character supplied in register s0.
;If the character is in the range 'a' to 'z', it is converted
;to the equivalent upper case character in the range 'A' to 'Z'.
;All other characters remain unchanged.
;
;Registers used s0.
;
upper_case: COMPARE s0, 61 ;eliminate character codes below 'a' (61 hex)
RETURN C
COMPARE s0, 7B ;eliminate character codes above 'z' (7A hex)
RETURN NC
AND s0, DF ;mask bit5 to convert to upper case
RETURN
;
;
;Convert character '0' to '9' to numerical value in range 0 to 9
;
;The character supplied in register s0. If the character is in the
;range '0' to '9', it is converted to the equivalent decimal value.
;Characters not in the range '0' to '9' are signified by the return
;with the CARRY flag set.
;
;Registers used s0.
;
onechar_to_value: ADD s0, C6 ;reject character codes above '9' (39 hex)
RETURN C ;carry flag is set
SUB s0, F6 ;reject character codes below '0' (30 hex)
RETURN ;carry is set if value not in range
;
;
;Determine the numerical value of a two character decimal string held in
;scratch pad memory such the result is in the range 0 to 99 (00 to 63 hex).
;
;The string must be stored in two consecutive memory locations and the
;location of the first (tens) character supplied in the s1 register.
;The result is provided in register s2. Strings not using characters in the
;range '0' to '9' are signified by the return with the CARRY flag set.
;
;Registers used s0, s1 and s2.
;
twochar_to_value: FETCH s0, (s1) ;read 'tens' character
CALL onechar_to_value ;convert to numerical value
RETURN C ;bad character - CARRY set
LOAD s2, s0
SL0 s2 ;multiply 'tens' value by 10 (0A hex)
SL0 s2
ADD s2, s0
SL0 s2
ADD s1, 01 ;read 'units' character
FETCH s0, (s1)
CALL onechar_to_value ;convert to numerical value
RETURN C ;bad character - CARRY set
ADD s2, s0 ;add units to result and clear CARRY flag
RETURN
;
;
;Convert hexadecimal value provided in register s0 into ASCII characters
;
;The value provided must can be any value in the range 00 to FF and will be converted into
;two ASCII characters.
; The upper nibble will be represented by an ASCII character returned in register s2.
; The lower nibble will be represented by an ASCII character returned in register s1.
;
;The ASCII representations of '0' to '9' are 30 to 39 hexadecimal which is simply 30 hex
;added to the actual decimal value. The ASCII representations of 'A' to 'F' are 41 to 46
;hexadecimal requiring a further addition of 07 to the 30 already added.
;
;Registers used s0, s1 and s2.
;
hex_byte_to_ASCII: LOAD s1, s0 ;remember value supplied
SR0 s0 ;isolate upper nibble
SR0 s0
SR0 s0
SR0 s0
CALL hex_to_ASCII ;convert
LOAD s2, s0 ;upper nibble value in s2
LOAD s0, s1 ;restore complete value
AND s0, 0F ;isolate lower nibble
CALL hex_to_ASCII ;convert
LOAD s1, s0 ;lower nibble value in s1
RETURN
;
;Convert hexadecimal value provided in register s0 into ASCII character
;
;Register used s0
;
hex_to_ASCII: SUB s0, 0A ;test if value is in range 0 to 9
JUMP C, number_char
ADD s0, 07 ;ASCII char A to F in range 41 to 46
number_char: ADD s0, 3A ;ASCII char 0 to 9 in range 30 to 40
RETURN
;
;
;Send the two character HEX value of the register contents 's0' to the UART
;
;Registers used s0, s1, s2
;
send_hex_byte: CALL hex_byte_to_ASCII
LOAD UART_data, s2
CALL send_to_UART
LOAD UART_data, s1
CALL send_to_UART
RETURN
;
;
;
;Send the six character HEX value of the register contents [s9,s8,s7] to the UART
;
;Registers used s0, s1, s2
;
send_hex_3bytes: LOAD s0, s9
CALL send_hex_byte
LOAD s0, s8
CALL send_hex_byte
LOAD s0, s7
CALL send_hex_byte
RETURN
;
;
;Convert the HEX ASCII characters contained in 's3' and 's2' into
;an equivalent hexadecimal value in register 's0'.
; The upper nibble is represented by an ASCII character in register s3.
; The lower nibble is represented by an ASCII character in register s2.
;
;Input characters must be in the range 00 to FF hexadecimal or the CARRY flag
;will be set on return.
;
;Registers used s0, s2 and s3.
;
ASCII_byte_to_hex: LOAD s0, s3 ;Take upper nibble
CALL ASCII_to_hex ;convert to value
RETURN C ;reject if out of range
LOAD s3, s0 ;remember value
SL0 s3 ;multiply value by 16 to put in upper nibble
SL0 s3
SL0 s3
SL0 s3
LOAD s0, s2 ;Take lower nibble
CALL ASCII_to_hex ;convert to value
RETURN C ;reject if out of range
OR s0, s3 ;merge in the upper nibble with CARRY reset
RETURN
;
;
;Routine to convert ASCII data in 's0' to an equivalent HEX value.
;
;If character is not valid for hex, then CARRY is set on return.
;
;Register used s0
;
ASCII_to_hex: ADD s0, B9 ;test for above ASCII code 46 ('F')
RETURN C
SUB s0, E9 ;normalise 0 to 9 with A-F in 11 to 16 hex
RETURN C ;reject below ASCII code 30 ('0')
SUB s0, 11 ;isolate A-F down to 00 to 05 hex
JUMP NC, ASCII_letter
ADD s0, 07 ;test for above ASCII code 46 ('F')
RETURN C
SUB s0, F6 ;convert to range 00 to 09
RETURN
ASCII_letter: ADD s0, 0A ;convert to range 0A to 0F
RETURN
;
;
;Read two hex characters from UART and convert to single byte data
;
obtain_8bits: CALL read_upper_case ;obtain one byte from UART
LOAD s3, s0
CALL read_upper_case
LOAD s2, s0
CALL ASCII_byte_to_hex
RETURN
;
;**************************************************************************************
;Text messages
;**************************************************************************************
;
;
;Send Carriage Return to the UART
;
send_CR: LOAD UART_data, character_CR
CALL send_to_UART
RETURN
;
;Send a space to the UART
;
send_space: LOAD UART_data, character_space
CALL send_to_UART
RETURN
;
;
;Send 'PicoBlaze NOR FLASH Programmer' string to the UART
;
send_welcome: CALL send_CR
CALL send_CR
LOAD UART_data, character_P
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_c
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_B
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_z
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
CALL send_space
LOAD UART_data, character_N
CALL send_to_UART
LOAD UART_data, character_O
CALL send_to_UART
LOAD UART_data, character_R
CALL send_to_UART
CALL send_space
LOAD UART_data, character_F
CALL send_to_UART
LOAD UART_data, character_L
CALL send_to_UART
LOAD UART_data, character_A
CALL send_to_UART
LOAD UART_data, character_S
CALL send_to_UART
LOAD UART_data, character_H
CALL send_to_UART
CALL send_space
LOAD UART_data, character_P
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_g
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_m
CALL send_to_UART
LOAD UART_data, character_m
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
CALL send_space
LOAD UART_data, character_v
CALL send_to_UART
LOAD UART_data, character_1
CALL send_to_UART
LOAD UART_data, character_fullstop
CALL send_to_UART
LOAD UART_data, character_0
CALL send_to_UART
LOAD UART_data, character_0
CALL send_to_UART
CALL send_CR
CALL send_CR
RETURN
;
;
;
;Send 'Waiting_MCS_file' string to the UART
;
send_Waiting_MCS_file: LOAD UART_data, character_W
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_n
CALL send_to_UART
LOAD UART_data, character_g
CALL send_to_UART
CALL send_space
LOAD UART_data, character_f
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
send_MCS_file: CALL send_space
LOAD UART_data, character_M
CALL send_to_UART
LOAD UART_data, character_C
CALL send_to_UART
LOAD UART_data, character_S
CALL send_to_UART
CALL send_space
LOAD UART_data, character_F
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
CALL send_CR
RETURN
;
;
;Send 'Erase in progress' string to the UART
;
send_Erase_in_progress: CALL send_Erase
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_n
CALL send_to_UART
CALL send_space
LOAD UART_data, character_P
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_g
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
LOAD UART_data, character_s
CALL send_to_UART
CALL send_to_UART
CALL send_CR
RETURN
;
;
;Send 'Erase ' string to the UART
;
send_Erase: LOAD UART_data, character_E
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_s
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
CALL send_space
RETURN
;
;
;Send carriage return, 'OK' and carriage return to the UART
;
send_OK: CALL send_CR
LOAD UART_data, character_O
CALL send_to_UART
LOAD UART_data, character_K
CALL send_to_UART
CALL send_CR
RETURN
;
;
;
;Send menu to the UART
;
send_Menu: CALL send_CR
LOAD UART_data, character_E
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
CALL send_Erase
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
CALL send_to_UART
CALL send_CR
LOAD UART_data, character_B
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
CALL send_Erase
LOAD UART_data, character_b
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_c
CALL send_to_UART
LOAD UART_data, character_k
CALL send_to_UART
LOAD UART_data, character_s
CALL send_to_UART
CALL send_space
LOAD UART_data, character_1
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_3
CALL send_to_UART
CALL send_CR
LOAD UART_data, character_P
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_P
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_g
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_m
CALL send_to_UART
CALL send_MCS_file
LOAD UART_data, character_W
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_W
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
CALL send_space
CALL send_byte
CALL send_CR
LOAD UART_data, character_R
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_R
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_d
CALL send_to_UART
CALL send_space
LOAD UART_data, character_2
CALL send_to_UART
LOAD UART_data, character_5
CALL send_to_UART
LOAD UART_data, character_6
CALL send_to_UART
CALL send_space
CALL send_byte
LOAD UART_data, character_s
CALL send_to_UART
CALL send_CR
LOAD UART_data, character_I
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_D
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
LOAD UART_data, character_v
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_c
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
CALL send_space
CALL send_ID
CALL send_CR
LOAD UART_data, character_H
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_H
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
LOAD UART_data, character_l
CALL send_to_UART
LOAD UART_data, character_p
CALL send_to_UART
CALL send_CR
LOAD UART_data, character_S
CALL send_to_UART
LOAD UART_data, character_minus
CALL send_to_UART
LOAD UART_data, character_S
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
LOAD UART_data, character_u
CALL send_to_UART
LOAD UART_data, character_s
CALL send_to_UART
CALL send_CR
RETURN
;
;
;Send 'ID' to the UART
;
send_ID: LOAD UART_data, character_I
CALL send_to_UART
LOAD UART_data, character_D
CALL send_to_UART
RETURN
;
;
;Send 'byte' to the UART
;
send_byte: LOAD UART_data, character_b
CALL send_to_UART
LOAD UART_data, character_y
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
RETURN
;
;
;Send 'Confirm Erase (Y/n) ' to the UART
;
send_Confirm: CALL send_CR
LOAD UART_data, character_C
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_n
CALL send_to_UART
LOAD UART_data, character_f
CALL send_to_UART
LOAD UART_data, character_i
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_m
CALL send_to_UART
CALL send_space
CALL send_Erase
LOAD UART_data, character_open
CALL send_to_UART
LOAD UART_data, character_Y
CALL send_to_UART
LOAD UART_data, character_divide
CALL send_to_UART
LOAD UART_data, character_n
CALL send_to_UART
LOAD UART_data, character_close
CALL send_to_UART
CALL send_space
RETURN
;
;
;Send 'Abort' to the UART
;
send_Abort: CALL send_CR
LOAD UART_data, character_A
CALL send_to_UART
LOAD UART_data, character_b
CALL send_to_UART
LOAD UART_data, character_o
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
CALL send_CR
RETURN
;
;Send 'address=' to the UART
;
send_address: CALL send_CR
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_d
CALL send_to_UART
CALL send_to_UART
LOAD UART_data, character_r
CALL send_to_UART
LOAD UART_data, character_e
CALL send_to_UART
LOAD UART_data, character_s
CALL send_to_UART
CALL send_to_UART
send_equals: LOAD UART_data, character_equals
CALL send_to_UART
RETURN
;
;
;Send 'data=' to the UART
;
send_data: CALL send_CR
LOAD UART_data, character_d
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
LOAD UART_data, character_t
CALL send_to_UART
LOAD UART_data, character_a
CALL send_to_UART
JUMP send_equals
;
;
;**************************************************************************************
;Interrupt Service Routine (ISR)
;**************************************************************************************
;
;An interrupt occurs whenever the status of the UART receiver FIFO 'half_full' flag
;changes.
;
;A change from Low to High means that the buffer is becoming full and therefore
;an XOFF character must be transmitted.
;
;A change from High to Low means that the buffer is starting to empty and therefore
;an XON character can be transmitted to restart the flow of new characters.
;
;
ADDRESS 3F5 ;place at end of memory to keep separate
ISR: STORE s0, ISR_preserve_s0 ;preserve register contents
INPUT s0, status_port ;test 'half_full' status of receiver buffer.
TEST s0, rx_half_full
JUMP Z, isr_send_xon
LOAD s0, character_XOFF
JUMP isr_send_character
isr_send_xon: LOAD s0, character_XON
isr_send_character: OUTPUT s0, UART_write_port
FETCH s0, ISR_preserve_s0 ;restore register contents
RETURNI ENABLE
;
;
;**************************************************************************************
;Interrupt Vector
;**************************************************************************************
;
ADDRESS 3FF
JUMP ISR
;
;