给8088单板机写一个迷你Boot

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!

 

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iCxhust

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值