U-boot-2014.10 transplantation 4th days ---- bare metal buzzer program, uboot2014.10 Transplantation
Hardware Platform: tq2440
Development Environment: Ubuntu-3.11
U-boot: 2014.10
This article allows reprint, please indicate the source: http://blog.csdn.net/fulinus
I. BUZZER asm Assembler:
/*********************************************************************** * File: beep.S * Version: 1.0.0 * Copyright: 2014 (c) fulinux <fulinux@sina.com> * Description: This ASM code used to turn beep on/off on TQ2440 board ***********************************************************************/#define GPBCON 0x56000010#define GPBDAT 0x56000014#define GPBUP 0x56000018#define DELAY 0X40000000 .text .align 2 .global _start_start: /*Set GPB5,GPB6,GPB7,GPB8 as GPIO OUTPUT mode*/ ldr r0, =GPBCON ldr r1, [r0] bic r1, r1, #0x03 /*Set GPBCON for GPB0 as 00 */ orr r1, r1, #0x01 /*Set GPBCON for GPB0 as GPIOOUT, 0x01*/ str r1, [r0] /*Set internal pullup resister*/ ldr r0, =GPBUP ldr r1, [r0] @orr r1, r1, #0x01 /*Set bit 0, disable pullup resister*/ bic r1, r1, #0x01 /*Clear bit 0, enable pullup resister*/ str r1, [r0]loop: /*Turn off beep*/ ldr r2, =GPBDAT ldr r3, [r2] orr r3, r3, #1 /*Set bit 0 as high level*/ str r3, [r2] ldr r0, =DELAY /*Sleep for a while*/ bl delay /*Turn on beep*/ ldr r3, [r2] bic r3, r3, #1 /*Set bit 0 as high level*/ str r3, [r2] ldr r0, =DELAY /*Sleep for a while*/ bl delay b loop /*Loop running*/delay: sub r0, r0, #1 cmp r0, #0x0 bne delay mov pc, lr
The program was modified based on the led. S program yesterday. The makefile file is the same as the file of yesterday, but the execution file name is changed:
BINAME = beep
2. ARM Assembly and C Language Combination
Switching from asm to C functions is also an important technical point. We need to do the following in the ARM assembler program:
1. Shut down the watchdog;
2. Block interruptions;
3. Jump to the main function in C code.
1. ARM Assembler
/*********************************************************************** * File: start.S * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: This ASM used to disable watch dog and interrupt, then call C code to * turn the buzzer on/off on FL2440 board. * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" * ***********************************************************************/#define pWTCON 0x53000000 /* Watch dog register address */#define INTMSK 0x4A000008 /* Interupt-Controller base addresses */#define INTSUBMSK 0x4A00001C .text .align 2 .global _start_start: /* Disable watch dog */ ldr r0, =pWTCON /*Save pwTCON address in r0*/ mov r1, #0x0 /*Set r1=0x0*/ str r1, [r0] /*Move the data in r1 to the address specify by r0*/ /* mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] ldr r0, =INTSUBMSK ldr r1, =0x7fff /*There are 15 bits used in INTSUBMSK on S3C2440*/ str r1, [r0] bl mainhalt_loop: b halt_loop
2. C Language Program
/*********************************************************************** * File: beep.c * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: This C code used to turn buzzer on/off on FL2440 board * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" * ***********************************************************************/#define GPBCON (*(unsigned long volatile *)0x56000010)#define GPBDAT (*(unsigned long volatile *)0x56000014)#define GPBUP (*(unsigned long volatile *)0x56000018)#define BEEP 0 /*Buzzer us GPB0 */#define DELAY_TIME 40000000static inline void delay (unsigned long loops){ __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0" (loops));}int main(void){ GPBCON = (GPBCON|0x3)&0x1; /* Set GPB0 as GPIO output mode(0x01) */ GPBUP &= ~1; /* Enable pullup resister */ GPBDAT |= 0x560; while(1) { GPBDAT &= ~(1<<BEEP); /* Set Beep GPIO as low level */ delay(DELAY_TIME); GPBDAT |= 1<<BEEP; /* Set Beep GPIO as high level */ delay(DELAY_TIME); }}
Obviously, we need to execute the ARM assembler program first, and then jump from the assembler program to the C program. However, the compiler does not know whether to put the C code segment or the ARM assembly code segment first, therefore, we need to inform the compiler how to compile and connect. There is a lds file. The content in this file determines the placement relationship of each code segment in the program. You can see in the makefile file below how to pass the file to the compiler.
3. lds File
/*********************************************************************** * File: beep.lds * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: Cross tool link text, refer to u-boot.lds * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" ***********************************************************************/ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{ . = 0x33000000; .text : { start.o(.text*) /* by fulinux modified */ *(.text*) *(.rodata) } .data ALIGN(4): { *(.data) } .bss ALIGN(4): { *(.bss) }
4. makefile
# ***********************************************************************# * File: makefile# * Version: 1.0.0# * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com># * Description: Makefile used to cross compile the ASM and C source code# * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"# *# ***********************************************************************BINAME = beepTEXTBASE = 0x33000000CROSS = /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-CC = $(CROSS)gccLD = $(CROSS)ldAR = $(CROSS)arOBJCOPY = $(CROSS)objcopyOBJDUMP = $(CROSS)objdumpSTRIP = $(CROSS)stripREADELF = $(CROSS)readelfCFLAGS = -g -O2 -Wall -nostdinc -nostdlib -fno-builtinAFLAGS = $(CFLAGS) -D__ASSEMBLY__LDSCRIPT = ${BINAME}.ldsLDFLAGS = -nostartfiles -T $(LDSCRIPT) -Ttext $(TEXTBASE)SRC_C = $(wildcard *.c)SRC_S = $(wildcard *.S)OBJ_C = $(patsubst %.c,%.o,$(SRC_C))OBJ_S = $(patsubst %.S,%.o,$(SRC_S))OBJ_ALL = $(OBJ_C) $(OBJ_S).PHONY : allall: ${OBJ_ALL} ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL} ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin rm -f *.elf *.o%.o: %.S $(CC) $(AFLAGS) -c -o $@ $<%.o: %.c $(CC) $(CFLAGS) -c -o $@ $<install: cp ${BINAME}.bin ~/winxp -f --reply=yesclean: rm -f *.elf *.o rm -f ${BINAME}.bin
File
LDSCRIPT = ${BINAME}.lds
That is, the beep. lds file.
5. Compile and run
After compilation, the beep. bin program is burned to the SDRAM for execution through J-link:
h speed 12000 loadbin D:\kupan\temp\beep.bin 0x33000000 setpc 0x33000000 g
You will be able to hear it!
Iii. ARM Assembly of led marquee and C Language Program:
/*********************************************************************** * File: led.c * Version: 1.0.0 * Copyright: 2011 (c) Guo Wenxue <guowenxue@gmail.com> * Description: This C code used to turn LED0~LED4 on on FL2440 board * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011" * Modify: fulinux@sina.com ***********************************************************************/#define GPBCON (*(unsigned long volatile *)0x56000010)#define GPBDAT (*(unsigned long volatile *)0x56000014)#define GPBUP (*(unsigned long volatile *)0x56000018)#define LED0 5 /*LED0 use GPB5*/#define LED1 6 /*LED1 use GPB6*/#define LED2 7 /*LED2 use GPB7*/#define LED3 8 /*LED3 use GPB8*/#define DELAY_TIME 40000000static inline void delay (unsigned long loops){ __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0" (loops));}void led_init(void){ /* Set GPB5,GPB6,GPB7,GPB8 as GPIO mode(0x01) */ GPBCON = (GPBCON & ~0x3FC00) | 0x15400; GPBUP &= ~0x01E0; /* Set GPB5,GPB6,GPB7,GPB8 as high level, to turn LED0,LED1,LED2,LED3 off */ GPBDAT |= 0x01E0;}void led_off(void){ /* Set GPB5,GPB6,GPB7,GPB8 as high level, to turn LED0,LED1,LED2,LED3 off */ GPBDAT |= 0x01E0; delay(DELAY_TIME);}void led_on(int led){ /* Turn LED0 on */ GPBDAT &= ~(1<<led); delay(DELAY_TIME);}int main(void){ led_init(); while(1) { led_off(); led_on(LED0); led_on(LED1); led_on(LED2); led_on(LED3); }}
Other files are similar and slightly modified.