4.迷你Boot
1.为什么要给8088单板机系统,添加一个bootloader呢?
起初,能够用编程器,烧写测试程序,就已经非常开心了,毕竟自己苦苦琢磨8088系统了几年时间,一直感觉无从下手。尽管自己有了多年的单片机开发应用经验,比如51单片机和PIC单片机,但是市面上关于8088单板机如何制作的资料还是太少了。
由于8088单板机系统的开发,处于一个很原始的状态,市面上几乎得不到可用的仿真器,所以只能采取直接烧写程序,进行上电运行测试的办法。有时为了测试一个程序,要不断的卸下芯片,烧写,再按上芯片,上电测试的过程,就显得很繁琐了。
那么如何来解决这个问题呢?是否能够有一种相对来说比较简单的方法,把要测试的程序下载下去,而不用这么频繁的烧写芯片呢?考虑到,系统上已经设计实现了的串口,如果能够通过串口,将测试代码传下去,那么就可以解决这个问题了。要实现串口下载测试程序,实际上要完成的是两个微处理器系统间的通讯功能,一个是PC端的传输软件,一个是8088单板机机的接收程序。
PC端的传输软件,我们可以考虑使用现成的绿色软件,串口调试助手。因为要向8088单板机传输的程序,是二进制文件,而串口助手刚好有这个功能,这就给我们的开发省去了不少的麻烦事,毕竟这是一个完全由个人出于爱好完成的项目,时间有限,最好不什么都从头自己干,也是个可以接受明智之举。
2.bootloader的相关知识
Bootloader是嵌入式系统在加电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将 *** 作系统映像或固化的嵌入式应用程序装在到内存中然后跳转到 *** 作系统所在的空间,启动 *** 作系统运行。
对于嵌入式系统,Bootloader是基于特定硬件平台来实现的。因此,几乎不可能为所有的嵌入式系统建立一个通用的Bootloader,不同的处理器架构都有不同的Bootloader。Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。对于2块不同的嵌入式板而言,即使它们使用同一种处理器,要想让运行在一块板子上的bootloader程序也能运行在另一块板子上,一般也都需要修改Bootloader的源程序。
反过来,大部分Bootloader仍然具有很多共性,某些Bootloader也能够支持多种体系结构的嵌入式系统。例如,U-Boot就同时支持PowerPC、ARM、MIPS和X86等体系结构,支持的板子有上百种。通常,它们都能够自动从存储介质上启动,都能够引导 *** 作系统启动,并且大部分都可以支持串口和以太网接口。
在专用的嵌入式板子运行GNU/Linux系统已经变得越来越流行。一个嵌入式Linux系统从软件的角度看通常可以分为四个层次:
1、 引导加载程序。包括固化在固件(firmware)中的boot代码(可选),和BootLoader两大部分。
2、Linux内核。特定于嵌入式板子的定制内核以及内核的启动参数。
3、 文件系统。包括根文件系统和建立于Flash内存设备之上文件系统。通常用ramdisk来作为rootfs。
4、 用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。常用的嵌入式GUI有:MicroWindows和MiniGUI等。
通常,BootLoader是严重地依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的BootLoader几乎是不可能的。尽管如此,我们仍然可以对bootloader归纳出一些通用的概念来,以指导用户特定的BootLoader设计与实现。
3.8088单板机Bootloader代码解析
#make_bin#
; BIN is plain binary format similar to .com format, but not limited to 1 segment;
; All values between # are directives, these values are saved into a separate .binf file.
; Before loading .bin file emulator reads .binf file with the same file name.
; All directives are optional, if you don't need them, delete them.
; set loading address, .bin file will be loaded to this address:
#LOAD_SEGMENT=0500h#
#LOAD_OFFSET=0000h#
; set entry point:
#CS=0500h# ; same as loading segment
#IP=0000h# ; same as loading offset
; set segment registers
#DS=0500h# ; same as loading segment
#ES=0500h# ; same as loading segment
; set stack
#SS=0500h# ; same as loading segment
#SP=FFFEh# ; set to top of loading segment
; set general registers (optional)
#AX=0000h#
#BX=0000h#
#CX=0000h#
#DX=0000h#
#SI=0000h#
#DI=0000h#
#BP=0000h#
; add your code here
;---------------------------------------------------------------------------
;2017.2.2 增加字符串输出“OK...”
;2017.1.18 增加8255控制的数码管显示部分
;2017.1.17 修改led显示 加速初始化
;2016.10.9 接收到4个55H 跳转
;2016.10.7 修改程序下载后的触发方式,改成中断触发方式
;2016.10.6 增加串口接收指令集,下载到ram 0000:2000处,然后跳转到此处进行执行
;2016.10.2 将指令写到ram 0000:2000,然后串口跳转到0000:2000处进行执行
;2016.10.2 验证汇编EQU伪指令,PC16550 RECIEVE 1 BYTE
;2016.10.1 在中断中增加利用串口发送1个字节 0X99 的功能
;2016.10.1 成功对pc16550进行初始化,并且能够向PC端发送0X55 0XAA,非常高兴
;2016.9.30 增加PC16550驱动部分代码
;---------------------------------------------------------------------------
;ASM Example
;assume that the EPROM is mapped starting at FF000h
;and is 4Kbytes wide.(2732 type of device)
;
;assume that there is SRAM at 00000-OOOFFh (256 bytes)
;
;
;------------------------------------------------------*
; Packaging Program *
;This program is designed for bottle packaging in a *
;factory. The bottles pass across a sensor and for *
;each bottle the sensor sends a signal to one of the *
;input ports of the microprocessor (8Ox88). The *
;microprocessor checks to see if number of bottles has *
;reached 16. If so, the program sends another signal *
;to the packaging machine. *
;------------------------------------------------------*
;.Model small ;64K Max. size
;.Model large
;-------------------------------------------------------
;Declare some useful constants.
;inport equ 3F8h ;Input port address
;outport equ 2F8h ;Output port address
;MaxBot equ 10h ;set maximum number
;of bottles to 16
;-------------------------------------------------------
; DO NOT use a data segment. All fixed data that you
; want in ROM can be put in the code segment using the
; same compiler directives you used in the data segment
;-------------------------------------------------------
; .CODE
;ORG 0100h ;put permanent data here.
;start,of fixed data(rather arbitrary,
;only must not be at the high end of
;EPROM). The ORG statement MUST FOLLOW
;the segment declaration.
;tblstrt: db 0FFh ;Just defining some useless data.
;db 0EEh
;db 0DDh
;tblend: db 0A5h ;End of useless data
;---------------------------------------------------------
;This is where the code "really" starts!
;LCR EQU 8003H
LSR EQU 1f5H
DATA_BRDL EQU 1F0H
ORG 0000h ;keep data and code areas separate
start: nop
;-------------------------------
;init
;-------------------------------
mov ax,0
mov ds,ax
mov ss,ax
mov ax,6fffh
mov sp,ax
;-----------------------------
;init si as 2000h
;-----------------------------
mov ax,2000h
mov bx,ax
;----------------------------------------
;LIGHT LED
;---------------------------------------
;MOV AL,0FH
CALL NMI_INIT
mov al,0f0h
mov byte ptr ds:[80h],al
mov al,00h
mov byte ptr ds:[81h],al
mov al,00h
mov byte ptr ds:[1000h],al
mov byte ptr ds:[1001h],0
CALL CMD_WR
CALL COM_INIT
;-----------------------------------------------------
;main loop
;-----------------------------------------------------
mov ax,2000h
mov bx,ax
MOV DX,DATA_BRDL
;IN AL,DX
;OUT DX,AL
mov ax,bx
; out dx,ah
out dx,al
mov al,ah
out dx,al
CALL OK_STR
;-----------------------------------------------
MOV AX,0F000H
MOV ES,AX
;MOV DI,STR1
LEA DI,STR1
CALL STR_OUT
;-----------------------------------------------
; CALL OK_STR
MOV CX,200
LOOP $
;---------------------------------------------------
MOV CX,3
S100:
MOV DX,800H
MOV AL,0F0H
OUT DX,AL
CALL DELAY
CALL DELAY
MOV AL,0
OUT DX,AL
CALL DELAY
CALL DELAY
CALL OK_STR
LOOP S100
MOV DX,800H
MOV AL,0F0H
OUT DX,AL
; CALL OK_STR
call init8255
call disp_8255
; CALL OK_STR
;-----------------------------------------------
MOV AX,0F000H
MOV ES,AX
;MOV DI,STR1
;LEA DI,STR2
;CALL STR_OUT
NOP
NOP
LEA DI,STR1
CALL STR_OUT
;-----------------------------------------------
; CALL OK_STR
main:
nop
call rcv_inc
mov al,byte ptr ds:[1000h]
cmp al,55h
jnz next_p
mov byte ptr ds:[100h],00H
mov byte ptr ds:[101h],20H
mov byte ptr ds:[102h],00H
mov byte ptr ds:[103h],00H
JMP DWORD PTR DS:[100H]
next_p:nop
jmp main
;------------------------------------------------------
;main loop end
;------------------------------------------------------
START01:
NOP
;mov al,55h
;mov byte ptr ds:[80h],al
mov al,byte ptr ds:[80h]
;OUT 10H,AL
mov dx,0ffh
out dx,al
CALL DELAY
CALL DELAY
;CALL DELAY
;CALL DELAY
;-----------------------------------------
;OFF LED
;-----------------------------------------
;MOV AL,00H
;mov al,0aah
;mov byte ptr ds:[80h],al
mov al,byte ptr ds:[81h]
;OUT 10H,AL
mov dx,0ffh
out dx,al
CALL RCV
NOP
NOP
CALL COM_TEST
CALL DELAY
CALL DELAY
CALL DELAY
CALL DELAY
jmp START01 ;START again
;---------------------------------------------------
;将指令写到RAM 0000:2000处
;b0 f0 e6 10 eb fa
; loopx:mov al,0f0h
; out 10h,al
; jmp loopx
;----------------------------------------------------
CMD_WR PROC NEAR
mov byte ptr ds:[2000h],0B0H
mov byte ptr ds:[2001h],0F0H
mov byte ptr ds:[2002h],0E6H
mov byte ptr ds:[2003h],10H
mov byte ptr ds:[2004h],0EBH
mov byte ptr ds:[2005h],0FAH
RET
CMD_WR ENDP
;---------------------------------------------------
;16650 init
;---------------------------------------------------
COM_INIT PROC NEAR
;LINE
MOV AL,8AH
MOV DX,1F3H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;LSB
MOV AL,120
MOV DX,1F0H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;MSB
MOV AL,0
MOV DX,1F1H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;LINE
;MOV AL,0AH
MOV AL,03H
MOV DX,1F3H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
;FIFO
MOV AL,07H
MOV DX,1F2H
OUT DX,AL
CALL DELAY
;CALL DELAY
;CALL DELAY
;CALL DELAY
MOV DX,800H
MOV AL,0AAH
OUT DX,AL
RET
COM_INIT ENDP
;---------------------------------------------------
;16650 SEND 1 BYTE
;---------------------------------------------------
COM_TEST PROC NEAR
MOV AL,55H
MOV DX,1F0H
OUT DX,AL
CALL DELAY
MOV AL,0AAH
MOV DX,1F0H
OUT DX,AL
RET
COM_TEST ENDP
;---------------------------------------------------
;PC16550 RECIEVE 1 BYTE
;---------------------------------------------------
RCV PROC NEAR
PUSH AX
MOV DX,LSR
IN AL,DX
TEST AL,01H
JZ RCV_EXIT
MOV DX,DATA_BRDL
IN AL,DX
OUT DX,AL
;JMP WORD PTR DS:[2000H]
;MOV AX,2000H
;MOV DS:[100H],AX
;MOV WORD PTR DS:[102H],0
mov byte ptr ds:[100h],00H
mov byte ptr ds:[101h],20H
mov byte ptr ds:[102h],00H
mov byte ptr ds:[103h],00H
JMP DWORD PTR DS:[100H]
NOP
RCV_EXIT:
NOP
POP AX
RET
RCV ENDP
;--------------------------------------------------------
;pc16550 接收指令集,并写到指定的ram位置
;--------------------------------------------------------
rcv_inc proc near
PUSH AX
MOV DX,LSR
IN AL,DX
TEST AL,01H
JZ RCVinc_EXIT
MOV DX,DATA_BRDL
IN AL,DX
OUT DX,AL
;mov ax,si
;out dx,ah
;out dx,al
;mov al,ah
;out dx,al
mov byte ptr ds:[bx],al
add bx,1
;*****************************************************
;
;*****************************************************
cmp al,55h
jnz set_0
add byte ptr ds:[1001h],1
cmp byte ptr ds:[1001h],4
jnz skip
mov byte ptr ds:[1000h],55h
;mov byte ptr ds:[1001h],0
jmp skip
set_0:
mov byte ptr ds:[1001h],0
skip:
nop
;*****************************************************
cmp al,0ffh
jnz RCVinc_EXIT
jz RCVinc_EXIT
;JMP WORD PTR DS:[2000H]
;MOV AX,2000H
;MOV DS:[100H],AX
;MOV WORD PTR DS:[102H],0
mov byte ptr ds:[100h],00H
mov byte ptr ds:[101h],20H
mov byte ptr ds:[102h],00H
mov byte ptr ds:[103h],00H
;JMP DWORD PTR DS:[100H]
mov ax,5
mov cx,ax
mov ax,2000h
mov si,ax
;mov
s:
mov al,byte ptr ds:[si];
MOV DX,DATA_BRDL
OUT DX,AL
add si,1
;loop s
;cmp si,2100h
;mov cx,500
;s1: loop s1
;mov ax,1f5h
mov dx,1f5h
s2: in al,dx
test al,20h
jz s2
mov ax,si
cmp ax,2fffh
jnz s
MOV DX,DATA_BRDL
OUT DX,AL
mov al,ah
out dx,al
;JMP DWORD PTR DS:[100H]
NOP
RCVinc_EXIT:
NOP
POP AX
RET
;ret
rcv_inc endp
;---------------------------------------------------
;DELAY PROC
;---------------------------------------------------
DELAY PROC NEAR
;push
PUSH CX
PUSH BX
NOP
NOP
mov bx,10
del1:
mov cx,5882
del2:
loop del2
dec bx
jnz del1
;pop cx
;pop bx
POP BX
POP CX
RET
DELAY ENDP
;----------------------------------------------
;nop delay
;----------------------------------------------
delay_100 proc near
PUSH AX
mov al,0FFh
;INC AL
mov byte ptr ds:[80h],al
NOP
NOP
NOP
POP AX
ret
delay_100 endp
;---------------------------------------------------
;DELAY01 PROC
;---------------------------------------------------
DELAY01:
;push
NOP
NOP
mov bx,10
del10:
mov cx,5882
del20:
loop del20
dec bx
jnz del10
;pop cx
;pop bx
RET
;---------------------------------------------------------
;NMI_INIT PROC
;---------------------------------------------------------
NMI_INIT:
PUSH ES
XOR AX,AX
MOV ES,AX
MOV AL,02H
XOR AH,AH
SHL AX,1
SHL AX,1
MOV SI,AX
MOV AX,OFFSET NMI_ISR
MOV ES:[SI],AX
INC SI
INC SI
MOV BX,CS
MOV ES:[SI],BX
POP ES
RET
;--------------------------------------------------------
;NMI_ISR
;--------------------------------------------------------
NMI_ISR:
NOP
NOP
mov al,byte ptr ds:[80h]
;mov al,0FFh
INC AL
mov byte ptr ds:[80h],al
;MOV AL,0FFH
;OUT 10H,AL
;CALL DELAY01
NOP
call delay_100
;CALL DELAY
;CALL DELAY
;CALL DELAY
;-------------------------------
;DELAY
;-------------------------------
;-------------------------------
;uart send 0x99 function
;-------------------------------
mov al,55h
mov byte ptr ds:[1000h],al
MOV AL,0a5H
MOV DX,1F0H
OUT DX,AL
NOP
NOP
IRET
;-----------------------------
;8255 init
;-----------------------------
init8255 proc near
mov dx,203h
;mov al,80h
mov al,89h;port a,b as output port c as input
out dx,al
ret
init8255 endp
;------------------------------
;8255 for disp
;------------------------------
disp_8255 proc near
mov al,11000000b ;'1'
mov dx,200h
out dx,al
;8255 port b
mov al,00h
mov dx,201h
out dx,al
ret
disp_8255 endp
;---------------------------------------
;OK STR OUT
;---------------------------------------
OK_STR PROC NEAR
MOV DX,DATA_BRDL
MOV AL,'O'
OUT DX,AL
MOV AL,'K'
OUT DX,AL
MOV AL,'.'
OUT DX,AL
MOV AL,'.'
OUT DX,AL
MOV AL,'.'
OUT DX,AL
RET
OK_STR ENDP
;-----------------------------------------------------------
;增加Boot启动输出“www.i8088.com”信息
;2019.11.3
;-----------------------------------------------------------
STR_OUT PROC NEAR
NOP
STR_LOOP:
MOV DX,DATA_BRDL
MOV AL,BYTE PTR ES:[DI]
CMP AL,'$'
JZ STR_EXIT
;MOV AL,'X'
OUT DX,AL
;MOV AL,'X'
;OUT DX,AL
MOV CX,200
LOOP $
INC DI
JMP STR_LOOP
STR_EXIT:
NOP
RET
STR_OUT ENDP
STR1 DB 'www.i8088.cn',13,10,'$'
STR2 DB 'just for fun!',13,10,'$'
;**********************************************************************
;**********************************************************************
;EPROM goes from XX000-XXFFFh. But, because of memory mapping,
;the XX is actually Ffh address. The jump must bea ;near jump (2 byte,
;relative address) so that the jump is relocatable. Otherwise
;a 4byte absolute address is put in.
;
;org 0FF0h ;restart address
; .CODE
;org 0eff0h ;27c512 64k rom,烧写时需手动移到fff0处
;jmp far ptr start;
;again: mov al,01h
;again1: out 10h,al
;jmp 0f000:0100
end
HLT ; halt!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)