Nios 2 subroutine keeps running after return

45 Views Asked by At

I am writing Nios 2 code on an emulator, It takes the state of a button, if it is high, then looks at a couple of switches and get the number from the switch it is assigned to then puts that number into a seven segment display. This loops 4 times and is supposed to stop after it runs 4 times buyt it keeps resetting its counter after it runs 4 times.

this is set to run on an emulator called cpulator. the specific type is the de-10 lite https://cpulator.01xz.net/?sys=nios-de10-lite I need this block of code to run like a subroutine. call it once, have it gather the numbers, then exit and move on to the next instruction after it was called.

.macro push reg
subi sp, sp, 4
stw    \reg, 0(sp)
.endm

.macro pop reg
ldw    \reg, 0(sp)
addi sp, sp, 4
.endm

.equ IO_BASE, 0xff200000
.equ LED, 0x00
.equ SWITCH, 0x40
.equ BUTTON, 0x50
.equ IO_BASE, 0xff200000 
.equ SEG1,    0x20
.equ SEG2,    0x30
.equ TOS,     0x04000000   
.equ TIME,      0x2000
.equ TIME_CTRL, TIME+0x4
.equ TIME_START,TIME+0x8
.global _start
_start:
call _get_the_numbers

_stop: br _stop
_get_the_numbers:
movui r22, 0x0200
movi r19, 4
movi r18, 0
movi r17, 1
movia sp,  TOS
movia r23, IO_BASE # device base address
check_button0:
ldwio r2, BUTTON(r23) # read buttons 
andi r2, r2, 0b01 # bit mask for button0
bne r2, r0, pressed # branch if button0 down


br check_button0
#r3 pulled value from switches
#r4 moved value
#r5 the dividing number
#r6 the divided number
#r7 the counter
#r8 the loop ender value
pressed:
ldwio r2, SWITCH(r23) # once up read switches
stwio r2, LED(r23) # write to LEDs
ldwio r3, LED(r23)
mov r4, r3 # moves the exponed number into r3
movi r5, 2 # sets r5 as the dividing num
movi r8, 1
movi r7, 0 # sets the counter as the 0
beq r3, r0, wait_for_up
call _expon
beq r6, r5, wait_for_up # checks to see of the exponed number is now 0 and sends to 
_expon:
div r6, r4, r5 #divides the exponed number by 2 
addi r7, r7, 1 # adds 1 to the counter
mov r4, r6
beq r4, r8, wait_for_up 
br _expon


wait_for_up:
ldwio r2, BUTTON(r23) # read buttons
andi r2, r2, 0b01 # bit mask for button0
bne r2, r0, numstuff # if down wait till up

seg7_output:  # arg r2 number
 push r2
 push r3                 #\
 push r4                 # \
 push r5                 #  stack
 push r6                 # /
 push r7                 #/    

 stwio r0, SEG1(r23)     # clear 7seg hex0
 stwio r0, SEG2(r23)     # clear 7seg hex1

 bne   r2, r0, seg7_not_zero # if number 0 send now no math
 ldb   r4, seg7_numbers(r0)  # get 0's 7seg equivalent
 stwio r4, SEG1(r23)         # display
 br _seg7_loop               # skip most code below
 
seg7_not_zero:
 movia r3, 1             # r3 divider
 movia r6, 0             # r6 counter
 seg7_max_digits:
  div   r4, r2, r3
  beq   r4, r0, _seg7_max_digits
  muli  r3, r3, 10
  addi  r6, r6, 1
  br seg7_max_digits
  _seg7_max_digits:
 
 seg7_loop:
  subi   r6, r6, 1
  movi   r4, 10
  div    r3, r3, r4       # new divider
  div    r4, r2, r3       # divide
  mov    r7, r4           # keep copy of raw number in r7    
  ldb    r5, seg7_numbers(r4)  # get new 7-seg number 
  muli   r4, r6, 8        # convert r6 to bytes
  sll    r5, r5, r4       # shift left
  cmpgti r4, r4, 24       # should we use the left most 7-seg address?
  bne    r4, r0, seg7_use_seg2
  ldwio  r4, SEG1(r23)    # get old 7-seg values 
  or     r4, r4, r5       # combine old and new values 
  stwio  r4, SEG1(r23)    # display
  br seg7_skip_seg2
  seg7_use_seg2: 
  ldwio  r4, SEG2(r23)    # get old 7-seg values 
  or     r4, r4, r5       # combine old and new values 
  stwio  r4, SEG2(r23)    # display
  seg7_skip_seg2:
  
  mul    r7, r7, r3       # get next number  
  sub    r2, r2, r7
  
  cmpeqi r4, r3, 1        # loop until 1s position
  beq    r4, r0, seg7_loop
  _seg7_loop:
 
  pop r7                  #\
  pop r6                  # \
  pop r5                  #  unstack     
  pop r4                  # /
  pop r3                  #/
  pop r2
  ret
  
start_timer:    # arg: r2 timer start value
 push  r2                    # stack
 stwio r0, TIME(r23)         # reset timer 
 sthio r2, TIME_START(r23)   # low halfword of counter start value
 srli  r2, r2, 16            # shift to hi-bits
 sthio r2, TIME_START+4(r23) # high halfword of counter start value  
 movi  r2, 0b0100            # mask to start timer
 sthio r2, TIME_CTRL(r23)    # start the timer 
 pop   r2                    # unstack
 ret
  
wait_for_timeout: # no args
 push r2                     # stack
 wait_loop:
  ldwio  r2, TIME(r23)       # read timer status
  cmpeqi r2, r2, 0b10        # is it running ?
  bne    r2, r0, wait_loop   # loop until timer expired    
 pop r2                      # unstack
 ret
 
numstuff:
#ldw r21, 0(r22) #pulls the previous number
#stw r7, 0(r22)  # stores the number into the first word
muli r11, r12, 10 #multiplies the prev num by 10
mov r10, r7 #moves the word to r10 for math
add r12, r11, r10
mov r2, r12
mov r22, r12
call seg7_output
movia r2, 1000000000   # value for 5 second timer
call start_timer      # start the timer
call wait_for_timeout # wait for it to timeout
add r18, r18, r17
bleu r18, r19, check_button0


.org 0x1000
.data
seg7_numbers: .byte 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x6f
                 #  0     1     2     3     4     5     6     7     8     9      
                 
                 
0

There are 0 best solutions below