戏说BIOS之Beep
2009-06-18 15:43
225 查看
戏说BIOS之Beep
1. Introduction
大凡用过电脑的朋友都应该听到过BIOS的报警声,有时 PC开机的时候就会听到嘀的一声,有过修理PC经验的话就更清楚了“一短内存刷新失败,二短内存校验错误,一长三短内存错误,一长八短显示错误”等等诸如此类,可能各家的BIOS定的规则不同,但目的都是通过报警音获悉系统运行状况,找出病灶对症下药(有点像中医诊断中“望闻问切”中的闻:))。
2. 8253/8254
Beep声我们都听过,但是有没有想过这是怎么实现的呢?带着疑惑随我开始探索之旅。提到这个Beep,它可算是历史悠久了,追溯到IBM的第一台PC, 那时工程师们可能觉得pc功能太过单调枯燥,于是他们就祈求上帝给我点声音吧,于是声音就有了J。他们将一个简单的扬声器加入了最初的pc硬件之中。光有speaker肯定是不足以产生音乐的,因为音乐得有音调和节奏才能组成。虽然我不懂音乐,但是我知道一点就是声音的高低和频率有关,所以还要有能制造频率的东东这就是8253/8254。既然提到我就大概的讲一讲8253/8254,8253/8254是可编程的定时器,8254是8253的增强版本差异主要在可以外接clock频率不同,其实使用上无差了。8253有三个独立工作16位的计数器t0、t1、t2分别使用40h、41h、42h port去操纵,除此之外还有一个43h port用于设定控制字。三个计数器分别编程,但是在使用之前必须先配置控制字,控制字主要用于选定哪一个计数器,选择计数器的工作模式等。控制字的格式如下表1所示:
表 1
其实这三个计数器在PC内部已经规划好了功能,基本上不需要用户参与了J
t0:用于系统时钟提供定时基准,它的输出端与中断控制器的IRQ0相连。
t1:用于DRAM更新的信号,每隔15.2us刷新一次。
t2:用于控制扬声器发声,作为speaker的音频频率。
所以我们知道t2用于提供speaker的音频频率,驱动speaker发生。这个部分早期驱动电路如下图1所示:
由上图1我们可以看到61h PB0控制T2的gate2,也就说只有将PB0 pull high T2才能工作。另外PB1与T2的输出端OUT2经过一个与门运算然后再驱动speaker,所以PB1也要pull high这样T2的输出就可以操纵speaker的频率了。图中的61h是没有介绍过的,那就再来聊聊61h port。61h在XT系统中集成在8255之中,8255是一颗可编程的外围接口芯片,61h对应8255的port B,它是一个8 bit的 IO port,每一个bit代表的意义如下表2所示:
表 2
AT以后8255已不再使用,port61h也使用别的IC代替了但是它的主要的bit功能还是保留了下来,所以仍然可以使用I/O指令读写61h port。
3. Beep~~~~~~
知道了以上的知识,我们就来写一个“一长三短的内存错误”的报警声玩玩咯J。需要做的工作有三个:a.通过操作61h port始能speaker input和t2 gate2;b.操作8253控制beep音的音调;c. 音调保持一定的时间(也就是声音的长短)。我们逐个的实现上述功能。
a最简单只要将61h port的bit0&1 pull high/low即可始能或者禁能,代码如下所示:
;----------------------------------------------------------------------------
; speak_set
; en/dis speaker input control&t2 gate2 control
; called with: cx
; used registers: ax
;-----------------------------------------------------------------------------
speak_set proc near
push ax
in al,61h
jcxz se_d
jmp se_e
ss_d:
and al,0fch
jmp se_done
ss_e:
or al,03h
ss_done:
out 61h,al
pop ax
ret
speak_set endp
b就需要设置8253计数器2的模式工作频率,操纵8253的步骤为先向43h port选择所要使用的计数器以及工作模式参数类型等,然后再向42h port装入t2的计数初始值,代码如下所示:
;----------------------------------------------------------------------------
; t2_set
; enable t2 & set work mode & out 2 frequency
; called with: di(frequency demanded)
; used registers: ax,dx
;-----------------------------------------------------------------------------
t2_set proc near
push dx
push ax
mov al,0b6h ;t2 lsb,msb,mode 3,binary
out 42h,al
mov dx,12h
mov ax,348ch
div di
out 42h,al
mov al,ah
out 42h,al
pop ax
pop dx
ret
t2_set endp
c可以通过执行loop达到延时的目的,可是loop延时和处理器的类型频率有关,不同种类的cpu执行同样指令所需的时钟周期不同,就算相同种类但是主频不同的cpu要达到同样的延时效果计数的基准也会不同。那么有没有精确延时的方法呢?书上给出的答案是通过检测61h port的bit4 ram刷新检查位,每隔15us该bit会发生一次变化,所以检测它可以获得比较精确的时间(我猜测这个bit会和8253 t1同步变化,因为t1的输出脉冲用作DRAM的刷新定时信号,而该信号要求15us刷新一次)。延时的代码如下所示:
;----------------------------------------------------------------------------
; delay
; delay time base on 15us unit
; called with: cx (counts of time unit)
; used registers: ax
;-----------------------------------------------------------------------------
delay proc near
push ax
dloop:
in al,61h
and al,10h
cmp al,ah
je dloop
mov ah,al
loop dloop
pop ax
ret
delay endp
以上就是beep的主要代码了,最后开放完整的source code供有兴趣的朋友参考。
REFF:
PC硬體元件控制詳解
《IBM-PC汇编语言程序设计》
Enjoy it!
That’s all!
Peter
1. Introduction
大凡用过电脑的朋友都应该听到过BIOS的报警声,有时 PC开机的时候就会听到嘀的一声,有过修理PC经验的话就更清楚了“一短内存刷新失败,二短内存校验错误,一长三短内存错误,一长八短显示错误”等等诸如此类,可能各家的BIOS定的规则不同,但目的都是通过报警音获悉系统运行状况,找出病灶对症下药(有点像中医诊断中“望闻问切”中的闻:))。
2. 8253/8254
Beep声我们都听过,但是有没有想过这是怎么实现的呢?带着疑惑随我开始探索之旅。提到这个Beep,它可算是历史悠久了,追溯到IBM的第一台PC, 那时工程师们可能觉得pc功能太过单调枯燥,于是他们就祈求上帝给我点声音吧,于是声音就有了J。他们将一个简单的扬声器加入了最初的pc硬件之中。光有speaker肯定是不足以产生音乐的,因为音乐得有音调和节奏才能组成。虽然我不懂音乐,但是我知道一点就是声音的高低和频率有关,所以还要有能制造频率的东东这就是8253/8254。既然提到我就大概的讲一讲8253/8254,8253/8254是可编程的定时器,8254是8253的增强版本差异主要在可以外接clock频率不同,其实使用上无差了。8253有三个独立工作16位的计数器t0、t1、t2分别使用40h、41h、42h port去操纵,除此之外还有一个43h port用于设定控制字。三个计数器分别编程,但是在使用之前必须先配置控制字,控制字主要用于选定哪一个计数器,选择计数器的工作模式等。控制字的格式如下表1所示:
Bit 0 | 计数值格式 0表示binary;1表bcd |
Bit1~3 | 模式选择 |
Bit4~5 | 读写指示 |
Bit6~7 | 选择计数器 |
其实这三个计数器在PC内部已经规划好了功能,基本上不需要用户参与了J
t0:用于系统时钟提供定时基准,它的输出端与中断控制器的IRQ0相连。
t1:用于DRAM更新的信号,每隔15.2us刷新一次。
t2:用于控制扬声器发声,作为speaker的音频频率。
所以我们知道t2用于提供speaker的音频频率,驱动speaker发生。这个部分早期驱动电路如下图1所示:
由上图1我们可以看到61h PB0控制T2的gate2,也就说只有将PB0 pull high T2才能工作。另外PB1与T2的输出端OUT2经过一个与门运算然后再驱动speaker,所以PB1也要pull high这样T2的输出就可以操纵speaker的频率了。图中的61h是没有介绍过的,那就再来聊聊61h port。61h在XT系统中集成在8255之中,8255是一颗可编程的外围接口芯片,61h对应8255的port B,它是一个8 bit的 IO port,每一个bit代表的意义如下表2所示:
Bit0 | t2 gate2 控制位 |
Bit1 | Speaker 控制位 |
Bit2 | DIP相关 |
Bit3 | 录音马达 |
Bit4 | RAM同步更新检查位 |
Bit5 | I/0通道检查 |
Bit6 | Keyboard 电平控制 |
Bit7 | Keyboard 始能控制 |
AT以后8255已不再使用,port61h也使用别的IC代替了但是它的主要的bit功能还是保留了下来,所以仍然可以使用I/O指令读写61h port。
3. Beep~~~~~~
知道了以上的知识,我们就来写一个“一长三短的内存错误”的报警声玩玩咯J。需要做的工作有三个:a.通过操作61h port始能speaker input和t2 gate2;b.操作8253控制beep音的音调;c. 音调保持一定的时间(也就是声音的长短)。我们逐个的实现上述功能。
a最简单只要将61h port的bit0&1 pull high/low即可始能或者禁能,代码如下所示:
;----------------------------------------------------------------------------
; speak_set
; en/dis speaker input control&t2 gate2 control
; called with: cx
; used registers: ax
;-----------------------------------------------------------------------------
speak_set proc near
push ax
in al,61h
jcxz se_d
jmp se_e
ss_d:
and al,0fch
jmp se_done
ss_e:
or al,03h
ss_done:
out 61h,al
pop ax
ret
speak_set endp
b就需要设置8253计数器2的模式工作频率,操纵8253的步骤为先向43h port选择所要使用的计数器以及工作模式参数类型等,然后再向42h port装入t2的计数初始值,代码如下所示:
;----------------------------------------------------------------------------
; t2_set
; enable t2 & set work mode & out 2 frequency
; called with: di(frequency demanded)
; used registers: ax,dx
;-----------------------------------------------------------------------------
t2_set proc near
push dx
push ax
mov al,0b6h ;t2 lsb,msb,mode 3,binary
out 42h,al
mov dx,12h
mov ax,348ch
div di
out 42h,al
mov al,ah
out 42h,al
pop ax
pop dx
ret
t2_set endp
c可以通过执行loop达到延时的目的,可是loop延时和处理器的类型频率有关,不同种类的cpu执行同样指令所需的时钟周期不同,就算相同种类但是主频不同的cpu要达到同样的延时效果计数的基准也会不同。那么有没有精确延时的方法呢?书上给出的答案是通过检测61h port的bit4 ram刷新检查位,每隔15us该bit会发生一次变化,所以检测它可以获得比较精确的时间(我猜测这个bit会和8253 t1同步变化,因为t1的输出脉冲用作DRAM的刷新定时信号,而该信号要求15us刷新一次)。延时的代码如下所示:
;----------------------------------------------------------------------------
; delay
; delay time base on 15us unit
; called with: cx (counts of time unit)
; used registers: ax
;-----------------------------------------------------------------------------
delay proc near
push ax
dloop:
in al,61h
and al,10h
cmp al,ah
je dloop
mov ah,al
loop dloop
pop ax
ret
delay endp
以上就是beep的主要代码了,最后开放完整的source code供有兴趣的朋友参考。
REFF:
PC硬體元件控制詳解
《IBM-PC汇编语言程序设计》
Enjoy it!
That’s all!
Peter
相关文章推荐
- 戏说BIOS之Keyboard
- 戏说BIOS之PCI SCAN
- 戏说BIOS之Clock Generator
- 戏说BIOS之PCI SCAN
- 戏说BIOS之PCI SCAN
- 戏说BIOS之CMOS
- 戏说BIOS之Hello BIOS
- 戏说BIOS之CMOS
- 戏说BIOS之Clock Generator
- 电脑bios启动项快捷键大全(转)
- 东芝(Toshiba)笔记本进入BIOS方法--型号Dynabook RX3 TN240Y/3HD
- VT-x is disabled in the BIOS. (VERR_VMX_MSR_VMXON_DISABLED).
- vxworks for x86读取bios时间的解决方法 分类: vxWorks 2014-04-29 17:13 478人阅读 评论(0) 收藏
- 【我所认知的BIOS】—> uEFI AHCI Driver(6) AtaAtapiPassThruSupported的局部变量们
- [系统安装] 各种电脑进入BIOS方式
- beep的控制程序
- Why BIOS loads MBR into 0x7C00 in x86 ?
- Why BIOS loads MBR into 0x7C00 in x86 ?
- Why BIOS loads MBR into 0x7C00 in x86 ?
- SYS/BIOS 学习历程(一)Creating a SYS/BIOS Project with the TI Resource Explorer