I am trying to program a microprocessor using c/c++ with assembly subroutines.
I have a working assembly subroutine, Button_Push, that returns a 1 if a button has been pushed.
I have tested this subroutine in an assembly language program. I am really having trouble using the subroutine in C though.
I use the below make file:
---------------------------------------------------------------------------------------------------------------------------
# $* is prefix shared by target and dependent; $@ is name of target file
CFLAGS = -Wall -g -O2 -c -mno-xl-soft-mul
#CFLAGS = -Wall -O2 -c -mno-xl-soft-mul
LDFLAGS = -Wall -Wl,-T -Wl,linker.ld -Wl,-x
OBJS = buttontest.o Button_Push.o
NAME = buttontest
$(NAME).elf: $(OBJS)
mb-gcc -o $@ $(LDFLAGS) $(OBJS)
mb-objdump -S $@ >$(NAME).lst
mb-nm $@ >$(NAME).sym
# Suffix rules: tell how take file with first suffix and make it into
# file with second suffix
.cpp.o:
mb-gcc $(CFLAGS) $*.cpp
.s.o:
mb-as -gstabs -o $*.o $*.s
# mb-as -o $*.o $*.s
clean:
rm *.o
-----------------------------------------------------------------------------------------------------------------
Here is the buttontest.cpp file (i've tried compiling it as a c file by changing the above make file accordingly and
the cpp file itself. it gave me the exact same errors though, so I conclude that it has nothing to do with whether
its C/C++
/********************************************************************************************************************************
* @file: buttontest.cpp
*
* @purpose: Test the Button_Push subroutine in C/C++
*
* @author: Jake Bruce
*
* @date: 2/16/09
*
* @version: N/A
*******************************************************************************************************************************/
#define WEST_PUSH_MASK = 0x80;
#define EAST_PUSH_MASK = 0x100;
//prototypes for assembly subroutines
extern "C" int Button_Push(int swmask);
extern "C" void AsmInit (void);
int main()
{
volatile int *const LEDS = (int*)0x84130000; //LEDs is an unmodifiable, unoptimizable pointer to the integer located in memory location 0x84130000
AsmInit(); //call subroutine to initialize assembly vartiables
int count = 0;
*LEDS = 0; //store zero in LEDs initially
while(1)
{
if(Button_Push(0x80))
{
++count;
}
if(Button_Push(0x100))
{
--count;
}
*LEDS = count;
}
return 0;
}
------------------------------------------------------------------------------------------------------------------------------
And here is the .s file that has the subroutines i am trying to use with the above file.
###############################################################################
# Program: Button_Push.s
#
# Created by: Jake Bruce
#
# Description: Contains the Button_Push and AsmInit subroutines to be used
# in a C/C++ program
#
# Last modified: 2/16/09
###############################################################################
############################### ################################################
# Subroutine: AsmInit
#
# Description: Initializes all variables used by assembly subroutines
#
# Register Usage: None
###############################################################################
.equ SWITCHES, 0x84110000
.text
.globl PrevState
.ent PrevState
.align 2
AsmInit:
swi r0,r0,PrevState
swi r0,r0,SWITCHES
rtsd r15,8
nop
.end
############################### ################################################
# Subroutine: Button_Push
#
# Description: Returns a 1 in r3 if there is a debounced 0 to 1 transition
# on the switch specified by the mask in r5, a 0 otherwise.
#
# Register Usage: Input: r5 -- mask for appropriate button in SWITCHES
# Output: r3 -- 1 if 0-to-1 transition, 0 otherwise
# Scratch: r6-10
###############################################################################
#.data
#PrevState: .space 4
.text
.globl PrevState
.ent PrevState
.align 2
Button_Push:
lwi r6,r0,PrevState #get the value of the switch from the previous iteration
add r3,r0,r0 #initialize r3 to zero
lwi r2,r0,SWITCHES #get the current value stored in the switch
and r8,r2,r5 #mask value currently held in switches with the push button mask
beqi r8,thend #if the switch being checked is unpushed, the subroutine should end
rsub r7,r8,r6 #compare the current switch state to the previous switch state
beqi r7,thend #if the current state is the same as the previous state do nothing and end the subroutine
addi r7,r0,10000
delay1: #wait to see if the change sticks
addi r7,r7,-1
bgti r7,delay1
lwi r2,r0,SWITCHES
and r7,r2,r5
rsub r7,r7,r6 #compare the current value to the previous again to see if the change has stuck
beqi r7,thend #if the change didn't stick end the subroutine
addi r3,r0,1 #otherwise a 0-1 transition has been detected
thend:
swi r2,r0,PrevState #store which button was last pressed
rtsd r15,8
nop
.end
-----------------------------------------------------------------------------------------------
I am confused about how I am supposed to initialize the variable PrevState. Whenever I just use
.globl PrevState
.ent PrevState
it gives me an error messages saying "undefined reference to PrevState" for wherever PrevState is used
in the Button_Push subroutine. Can anyone help me figure out why it is doing this?
Furthermore if I try uncommenting out the .data segment above (the two lines that are commented out)
it will give me an error message at the end of both subroutines saying that "operation combines
symbols in different segments." To me it seems that this would mean that I am trying to define the
same thing more than once. Could anyone please help me clear up what the difference is between
.globl PrevState
.ent PrevState
and
.data
PrevState: .space 4
I'm trying to figure out where I'm supposed to use these two and what in particular I should do in this
instance. Any help would be appreciated