历史上的今天
返回首页

历史上的今天

今天是:2025年01月22日(星期三)

正在发生

2021年01月22日 | ARM开发板上uClinux内核移植

2021-01-22 来源:eefocus

简介:针对“如何在以S3C44B0X为核心的ARMSYS开发板上建立uClinux内核移植”的一个总结,其内容包括对Bootloader的功能分析和uClinux2.4.24发行版内核基础上针对S3C44B0X开发板进行修改的重点内容的逐一列举。


简述:针对“如何在以S3C44B0X为核心的ARMSYS开发板上建立uClinux内核移植”的一个总结,其内容包括对Bootloader的功能分析和uClinux2.4.24发行版内核基础上针对S3C44B0X开发板进行修改的重点内容的逐一列举。


2.Bootloader


2.1Bootloader概述


Boot Loader


就是在操作系统内核运行之前运行的一段程序。通过这段程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。因此,正确建立uClinux的移植的前提条件是具备一个与uClinux配套、易于使用的


Bootloader。


ARMSYS开发板提供了这样一个uClinux专用的Bootloader,该Bootloader程序烧录在系统的地址0x0处,每次上电即运行,能够正确完成硬件系统的初始化和uClinux的引导。


理论上,uClinux引导时并非一定需要一个独立于内核的Bootloader。然而,将Bootloader与内核分开设计能够使软件架构更加清晰,也有助于灵活地支持多种引导方式,实现一些有用的辅助功能。


ARMSYS提供的Bootloader的主要任务可以概括如下:


1.硬件初始化;


2.从主机下载新的内核映像和文件系统映像;


3.烧写NorFlash和Nandflash;


4.加载uClinux 内核映像并启动运行;


5.提供串行超级终端上的人机操作界面。


2.2存储空间分布


Bootloader采用默认的存储空间分布地址来加载uClinux内核、文件系统,并按照正确引导uClinux的运行。在ARMSYS的Bootloader中,默认的存储空间分布如下表:


内容 起始地址


存储介质


Bootloader程序空间 0x00000000


Flash


压缩内核映像 0x00010000


Flash


ROM文件系统映像 0x000e0000


Flash


内核运行地址 0x0c008000


SDRAM


压缩内核解压地址 0x0c100000


SDRAM


文件系统加载 0x0c700000 SDRAM


这个存储空间的分配方式也不是固定不变的,可以通过修改Bootloader中的相关代码来改变。


2.3Bootloader的工作


完整的Bootloader引导流程可描述如下:


硬件初始化阶段一


◎ 硬件初始化


◎ 复制二级中断异常矢量表


◎ 初始化各种处理器模式


◎ 复制RO和RW,清零ZI


(跳转到C代码入口函数)


硬件初始化阶段二


◎ 初始化本阶段使用到的硬件设备;


◎ 建立人机界面



实现映像文件的下载和烧录工具


◎ 实现映像文件的加载和运行工具


下面对上述各步骤进行逐一说明,并对与uClinux相关的内容详细加以说明。


2.3.1 硬件初始化


板子上电或复位后,程序从位于地址0x0的Reset Exception


Vector处开始执行,因此需要在这里放置Bootloader的第一条指令:b


ResetHandler,跳转到标号为ResetHandler处进行第一阶段的硬件初始化,主要内容为:关Watchdog


Timer,关中断,初始化PLL和时钟,初始化存储器控制器。比较重要的是PLL的输出频率要计算正确,ARMSYS中把它设置为64MHz;这实际上就是处理器的工作主频,这个时间参数在第二阶段计算SDRAM的刷新计数值和UART的波特率等参数时还要用到。


2.3.2建立二级异常中断矢量表


异常中断矢量表(Exception Vector


Table)是Bootloader与uClinux内核发生联系关键的地方之一。即使uClinux内核已经得到处理器的控制权运行,一旦发生中断,处理器还是会自动跳转到从0x0地址开始的第一级异常中断矢量表中的某个表项(依据于中断类型)处读取指令运行。


在编写 Bootloader时,地址0x0处的一级异常中断矢量表只需简单地包含向二级异常中断矢量表的跳转指令就可以。这样,就能够正确地将发生的事件交给


uClinux的中断处理程序来处理。对于uClinux内核,它在RAM空间中基地址为0xc000000处建立了自己的二级异常中断矢量表,因此,


Bootloader的第一级异常中断矢量表如下所示:


b ResetHandler ;Reset Handler


ldr


pc,=0x0c000004 ;Undefined Instruction Handler


ldr pc,=0x0c000008 ;Software


Interrupt Handler


ldr pc,=0x0c00000c ;Prefetch Abort Handler


ldr


pc,=0x0c000010 ;Data Abort Handler


b .


ldr pc,=0x0c000018 ;IRQ


Handler


ldr pc,=0x0c00001c ;FIQ Handler


LTORG


如果在Bootloader执行的全过程中都不必响应中断,那么上面的设置已能满足要求。但在我们的


ARMSYS上提供了USB下载器,需要用到中断,那么Bootloader必须在同样的地址(0xc000000)处配置自己的二级异常中断矢量表,以便同uClinux兼容。这张表事先存放在


Flash Memory里,引导过程中由Bootloader将其复制到RAM地址0x0C000000:


存放矢量表:


;IRQ ==the program put this phrase to 0xc000000


ExceptionHanlderBegin


b .


ldr pc, MyHandleUndef ; HandlerUndef


ldr


pc, MyHandleSWI ; HandlerSWI


ldr pc, MyHandlePabort ; HandlerPabort


ldr


pc, MyHandleDabort ; HandlerDAbort


b . ; HandlerReserved


ldr pc,


MyHandleIRQ ; HandlerIRQ


ldr pc, MyHandleFIQ ; HandlerFIQ


MyHandleUndef DCD HandleUndef ;reserve a word(32bit)


MyHandleSWI DCD


HandleSWI


MyHandlePabort DCD HandlePabort


MyHandleDabort DCD


HandleDabort


MyHandleIRQ DCD HandleIRQ


MyHandleFIQ DCD HandleFIQ


ExceptionHanlderEnd


建立二级矢量表:


;****************************************************


;* Setup IRQ handler


*


;****************************************************


ldr


r0,=(_IRQ_BASEADDRESS + 0x100)


ldr r2,=_IRQ_BASEADDRESS


add r3,r0,


#0x100


0


CMP r0, r3


STRCC r2, [r0], #4;cc:Carry clear;save R2 to R0


address, R0 =R0+ 4。


BCC %B0


ldr r1,=_IRQ_BASEADDRESS


ldr r0,=ExceptionHanlderBegin ;if there isn't


'subs pc,lr,#4' at 0x18, 0x1c


ldr r3,=ExceptionHanlderEnd


0


CMP r0, r3


;put the vector table at _IRQ_BASEADDRESS(0xc000000)


LDRCC r2, [r0],


#4


STRCC r2, [r1], #4


BCC %B0


ldr r1,=DIsrIRQ;put the IRQ judge program at


_IRQ_BASEADDRESS+0x80(0xc000080)


ldr r0,=IsrIRQ ;if there isn't 'subs


pc,lr,#4' at 0x18, 0x1c


ldr r3,=IsrIRQEnd


0


CMP r0, r3


LDRCC r2,


[r0], #4


STRCC r2, [r1], #4


BCC %B0


ldr r1, =MyHandleIRQ ;MyHandleIRQ point to DIsrIRQ


ldr r0,


=ExceptionHanlderBegin


ldr r4, =_IRQ_BASEADDRESS;


sub r0, r1, r0


add


r0, r0,r4


ldr r1, =DIsrIRQ


str r1, [r0]


定义Handlexxx:


^ (_IRQ_BASEADDRESS)


HandleReset # 4


HandleUndef # 4


HandleSWI #


4


HandlePabort # 4


HandleDabort # 4


HandleReserved # 4


HandleIRQ #


4


HandleFIQ # 4


^ (_IRQ_BASEADDRESS+0x80)


DIsrIRQ # 4


;IntVectorTable


^


(_IRQ_BASEADDRESS+0x100)


HandleADC # 4


HandleRTC # 4


HandleUTXD1 #


4


HandleUTXD0 # 4


HandleSIO # 4


HandleIIC # 4


HandleURXD1 #


4


HandleURXD0 # 4


HandleTIMER5 # 4


HandleTIMER4 # 4


HandleTIMER3 #


4


HandleTIMER2 # 4


HandleTIMER1 # 4


HandleTIMER0 # 4


HandleUERR01 #


4


HandleWDT # 4


HandleBDMA1 # 4


HandleBDMA0 # 4


HandleZDMA1 #


4


HandleZDMA0 # 4


HandleTICK # 4


HandleEINT4567 # 4


HandleEINT3 #


4


HandleEINT2 # 4


HandleEINT1 # 4


HandleEINT0 # 4


将异常中断矢量重构到SDRAM,这样的好处就是可以在其它的功能程序内对中断处理程序的地址任意赋值。为此,我们在44b.h文件中定义:


/* ISR */


#define pISR_RESET (*(unsigned


*)(_IRQ_BASEADDRESS+0x0))


#define pISR_UNDEF (*(unsigned


*)(_IRQ_BASEADDRESS+0x4))


#define pISR_SWI (*(unsigned


*)(_IRQ_BASEADDRESS+0x8))


#define pISR_PABORT (*(unsigned


*)(_IRQ_BASEADDRESS+0xc))


#define pISR_DABORT (*(unsigned


*)(_IRQ_BASEADDRESS+0x10))


#define pISR_RESERVED (*(unsigned


*)(_IRQ_BASEADDRESS+0x14))


#define pISR_IRQ (*(unsigned


*)(_IRQ_BASEADDRESS+0x18))


#define pISR_FIQ (*(unsigned


*)(_IRQ_BASEADDRESS+0x1c))


#define pISR_ADC (*(unsigned *)(_IRQ_BASEADDRESS+0x100))//0x20))


#define


pISR_RTC (*(unsigned *)(_IRQ_BASEADDRESS+0x104))//0x24))


#define pISR_UTXD1


(*(unsigned *)(_IRQ_BASEADDRESS+0x108))//0x28))


#define pISR_UTXD0


(*(unsigned *)(_IRQ_BASEADDRESS+0x10c))//0x2c))


#define pISR_SIO (*(unsigned


*)(_IRQ_BASEADDRESS+0x110))//0x30))


#define pISR_IIC (*(unsigned


*)(_IRQ_BASEADDRESS+0x114))//0x34))


#define pISR_URXD1 (*(unsigned


*)(_IRQ_BASEADDRESS+0x118))//0x38))


#define pISR_URXD0 (*(unsigned


*)(_IRQ_BASEADDRESS+0x11c))//0x3c))


#define pISR_TIMER5 (*(unsigned


*)(_IRQ_BASEADDRESS+0x120))//0x40))


#define pISR_TIMER4 (*(unsigned


*)(_IRQ_BASEADDRESS+0x124))//0x44))


#define pISR_TIMER3 (*(unsigned


*)(_IRQ_BASEADDRESS+0x128))//0x48))


#define pISR_TIMER2 (*(unsigned


*)(_IRQ_BASEADDRESS+0x12c))//0x4c))


#define pISR_TIMER1 (*(unsigned


*)(_IRQ_BASEADDRESS+0x130))//0x50))


#define pISR_TIMER0 (*(unsigned


*)(_IRQ_BASEADDRESS+0x134))//0x54))


#define pISR_UERR01 (*(unsigned


*)(_IRQ_BASEADDRESS+0x138))//0x58))


#define pISR_WDT (*(unsigned


*)(_IRQ_BASEADDRESS+0x13c))//0x5c))


#define pISR_BDMA1 (*(unsigned


*)(_IRQ_BASEADDRESS+0x140))//0x60))


#define pISR_BDMA0 (*(unsigned


*)(_IRQ_BASEADDRESS+0x144))//0x64))


#define pISR_ZDMA1 (*(unsigned


*)(_IRQ_BASEADDRESS+0x148))//0x68))


#define pISR_ZDMA0 (*(unsigned


*)(_IRQ_BASEADDRESS+0x14c))//0x6c))


#define pISR_TICK (*(unsigned


*)(_IRQ_BASEADDRESS+0x150))//0x70))


#define pISR_EINT4567 (*(unsigned


*)(_IRQ_BASEADDRESS+0x154))//0x74))


#define pISR_EINT3 (*(unsigned


*)(_IRQ_BASEADDRESS+0x158))//0x78))


#define pISR_EINT2 (*(unsigned


*)(_IRQ_BASEADDRESS+0x15c))//0x7c))


#define pISR_EINT1 (*(unsigned


*)(_IRQ_BASEADDRESS+0x160))//0x80))


#define pISR_EINT0 (*(unsigned


*)(_IRQ_BASEADDRESS+0x164))//0x84))


例如,我们要使用到Exint4567中断,定义好中断处理程序Meint4567Isr()后,仅需要一条语句:




pISR_EINT4567=(int)MEint4567Isr;


就能使中断发生后正确跳转到我们编写的处理程序上。


2.3.3 初始化各种处理器模式


ARM7TDMI支持7种Operation


Mode:User,FIQ,IRQ,Supervisor,Abort,System和Undefined。Bootloader需要依次切换到每种模式,初始化其程序状态寄存器(SPSR)和堆栈指针(SP)。


2.3.4 复制RO和RW,清零ZI


一个ARM由RO,RW和ZI三个段组成,其中RO为代码段,RW是已初始化的全局变量,ZI是未初始化的全局变量(对于GNU工具,对应的概念是


TEXT,DATA和BSS)。Bootloader要将RW段复制到RAM中,并将ZI段清零。编译器使用下列符号来记录各段的起始和结束地址:


|Image$$RO$$Base| :RO段起始地址


|Image$$RO$$Limit|


:RO段结束地址加1


|Image$$RW$$Base| :RW段起始地址


|Image$$RW$$Limit|


:ZI段结束地址加1


|Image$$ZI$$Base| :ZI段起始地址


|Image$$ZI$$Limit| :ZI段结束地址加1


需要注意的是,这些标号的值是根据链接器中设置的中ro-base和rw-base的设置来计算的,我们的Bootloader的对应设置是:ro-base =


0xc000000, rw-base = 0xc5f0000。


完成这个步骤后,第一阶段的硬件初始化就完成了。


BL Main


跳转到C语言程序,开始第二阶段的初始化和系统引导。


2.3.5 C语言中的硬件初始化


继续对硬件进行初始化,主要包括对以下设备的初始化:GPIO,Cache,Interrupt Controller,Watchdog


Timer和UARTs。S3C44B0X处理器内置data/instruction合一的8KB


Cache,且允许按地址范围设置两个Non-Cacheable区间。合理的配置是打开对RAM区间的Cache,关闭对其它地址区间(非存储器设备, I/O设备


)的Cache。所有硬件初始化完毕之后,开中断。


2.3.6 建立人机界面


引导过程的最后一步是在串行终端上建立人机界面,并等待用户输入命令。若接收到用户输入,则显示菜单模式或命令行模式的交互界面,等待用户进一步的命令。这里就不对此详细讨论了。


2.4加载uClinux内核


ARMSYS


提供的Bootloader支持两种uClinux启动运行方式:直接从SDRAM中的内核映像中运行;从flash将压缩格式的内核映像加载到


SDRAM,再从SDRAM运行。前者需要利用Bootloader提供的对映像文件下载的工具;后者则需要利用Bootloader提供的


flash烧录工具进行烧录,然后再加载运行。


压缩格式的uClinux内核映像文件都是由开头的一段自解压代码和后面的压缩数据部分组成。对于Kernel而言,由于是以压缩格式存放,因次只能以非XIP方式执行。自解压类型的uClinux


内核映像文件首先存放在Flash Memory中,由Bootloader加载到SDRAM中的0xc100000地址处,然后将控制权交给它。可执行的uClinux


Kernel将被解压到最终的执行空间,然后开始运行。压缩格式Image所占据的临时SDRAM空间可在随后由uClinux回收利用。


可以从flash拷贝到SDRAM解压运行,自然同样也可以直接下载到SDRAM运行。这对于调试内核都是非常方便的。对于压缩格式的内核映像文件(image.rom和image.ram)都可以直接下载到SDRAM的特定地址处,并从该地址开始运行(参考2.2节)。


2.5调用Kernel


Bootloader调用uClinux 内核的方法是直接跳转到Kernel的第一条指令处。


采用C语句:((void


(*)(void))ram_addr)();


2.6工具


ARMSYS


的Bootloader在人机界面上提供了8个功能项目,其中包括支持从主机通过USB口下载文件到目标板的SDRAM和Nandflash上;用


SDRAM中的数据烧写Flash


Memory。由于USB口下载速度快,利用这些功能项能够轻松地调试uClinux的内核(具体使用方法参考《uClinux移植包在ARMSYS上的使用说明》一文)。


对uClinux专用Bootloader的介绍到此,下面开始对uClinux的内核部分的移植进行说明。


3.uClinux2.4.24内核组成


◎arch:


arch目录下有多个子目录,它的每一个子目录都代表内核支持的一种CPU体系结构,每个子目录中又进一步分解为boot、mm、


kernel等子目录,分别包含与系统引导、内存管理、系统调用的进入和返回、终端处理以及其它内核中依赖于CPU和系统结构的底层代码。与ARM处理器(不带有MMU)相关的代码放在目录arch/armnommu下,与S3C44B0X相关的代码则放在目录arch/armnommu/match-


S3C44B0X。


◎ include:include子目录包括编译核心所需要的大部分头文件。与平台无关的头文件在


include/linux子目录下,与ARM处理器(不带MMU)相关的头文件在include/asm-armnommu子目录下,与


S3C44B0X相关的代码在include/asm-armnommu/arch-S3C44B0X目录下;



init:这个目录包含核心的初始化代码(注意:不是系统的引导代码),包含两个文件main.c和Version.c,这是研究核心如何工作的一个非常好的起点。



kernel:主要的核心代码,此目录下的文件实现了大多数linux系统的内核函数,其中最重要的文件当属sched.c;同样,和体系结构相关的代码在arch/*/kernel中;



drivers: 放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录:如,/block 下为块设备驱动程序,比如ide(ide.c)。



其他:例如mm ,这个目录包括所有独立于处理器体系结构的内存管理代码,如页式存储管理内存的分配和释放等;lib放置核心的库代码;net,核心与网络相关的代码;


ipc,这个目录包含核心的进程间通讯的代码;fs,所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件系统,例如fat和


ext2;Scripts,此目录包含用于配置核心的脚本文件等。


Linux Kernel Tree List


一般在每个目录下,都有一个.depend 文件和一个 Makefile


文件,这两个文件都是编译时使用的辅助文件,仔细阅读这两个文件对弄清各个文件这间的联系和依托关系很有帮助;而且,在有的目录下还有Readme


文件,它是对该目录下的文件的一些说明,同样有利于我们对内核源码的理解。


uClinux-dist-20040408发行包中的内核对S3C44B0X处理器的支持是不完整的,因此,我们不能够希望在make


config配置选项中选中44B0X目标板后,直接编译它来得到一个很好地支持44B0X开发板的内核映像,我们必须为内核打上补丁。针对ARMSYS


的补丁文件可以在http://www.hzlitai.com.cn/download/default.asp地址处下载得到。这款补丁是众多爱好


uClinux和44B0X处理器的网友们共同完成的。下一节我们就对这个补丁中的主要修改项目进行介绍和分析,从中了解uClinux移植中的要点。


4.移植项目及说明


4.1压缩内核代码起始地址修改


修改文件:uClinux-dist/linux-2.4.x/arch/armnommu/boot/Makefile


修改内容:


ifeq


($(CONFIG_BOARD_MBA44),y)


ZTEXTADDR = 0x0c100000


ZRELADDR =


0x0c008000


endif


说明:


ZTEXTADDR:自解压代码的起始地址。


ZRELADDR:内核解压后代码输出起始地址。


4.2处理器配置选项的修改


修改文件:uClinux-dist/linux-2.4.x/arch/armnommu/config.in

推荐阅读

史海拾趣

Component General Inc公司的发展小趣事

在技术创新的基础上,Component General Inc公司开始积极拓展市场。公司不仅在国内市场取得了良好的销售业绩,还积极开拓国际市场,与多家海外企业建立了合作关系。同时,公司也注重品牌建设,通过参加各种行业展会、举办技术研讨会等方式,提升公司的知名度和影响力。

台湾远翔(Feeling Technology)公司的发展小趣事

乔光电子成立于2009年,起初专注于过压、过流保护元器件的研发、生产和销售。公司凭借对技术的执着追求和对市场的敏锐洞察,迅速在行业内站稳脚跟。在创立初期,乔光电子就建立了先进的EMC实验室,致力于为客户提供顶级性能的过压、过流保护元器件和完整的电路保护解决方案。这一时期,乔光电子在福建和东莞建立了生产基地,为后续的快速发展奠定了坚实基础。

ACI [Applied Concepts, Inc.]公司的发展小趣事

在环保意识日益增强的今天,ACI公司积极响应国家号召,将绿色环保理念融入产品设计和生产过程中。公司采用环保材料和生产工艺,推出了一系列绿色电子产品。这些产品不仅具有优异的性能,而且符合环保标准,得到了消费者的广泛认可。通过倡导绿色环保理念,ACI成功引领了行业潮流,树立了良好的企业形象。

Fagor Electrónica公司的发展小趣事

进入1960年代,Fagor Electrónica迎来了其发展的第一个重大里程碑。1964年,公司成功启动了第一批硅整流器的制造。这一创新不仅提高了产品的性能,还为公司带来了更大的市场份额。硅整流器的推出标志着Fagor Electrónica在电子制造技术上的领先地位,也为其后续的发展奠定了坚实的基础。

Alpha Semiconductor公司的发展小趣事

Alpha Semiconductor位于美国加州硅谷的研发与生产基地是公司发展的重要支撑。在这里,公司拥有一流的研发团队和先进的生产设备,能够为客户提供高质量的产品和服务。硅谷作为全球科技创新的中心之一,为Alpha Semiconductor提供了丰富的技术资源和人才支持,使得公司能够不断推陈出新,保持在半导体行业的领先地位。

通过以上五个故事,我们可以看到Alpha Semiconductor公司在电子行业中的发展历程。从初创时期的代工服务起步,到后来的OEM定制产品、自主研发电源管理产品,再到高性能标准模拟和混合信号IC的制造实力,以及在美国硅谷的研发与生产基地的建立,每一个阶段都见证了公司的成长和进步。Alpha Semiconductor凭借着不断的技术创新和市场拓展,已经成为了半导体行业中的佼佼者。

ALLIED [Allied Electronics]公司的发展小趣事

Alpha Semiconductor位于美国加州硅谷的研发与生产基地是公司发展的重要支撑。在这里,公司拥有一流的研发团队和先进的生产设备,能够为客户提供高质量的产品和服务。硅谷作为全球科技创新的中心之一,为Alpha Semiconductor提供了丰富的技术资源和人才支持,使得公司能够不断推陈出新,保持在半导体行业的领先地位。

通过以上五个故事,我们可以看到Alpha Semiconductor公司在电子行业中的发展历程。从初创时期的代工服务起步,到后来的OEM定制产品、自主研发电源管理产品,再到高性能标准模拟和混合信号IC的制造实力,以及在美国硅谷的研发与生产基地的建立,每一个阶段都见证了公司的成长和进步。Alpha Semiconductor凭借着不断的技术创新和市场拓展,已经成为了半导体行业中的佼佼者。

问答坊 | AI 解惑

检测绝缘栅极双极型晶体管(IGBT)好坏的简易方法

1、判断极性首先将万用表拨在R×1KΩ挡,用万用表测量时,若某一极与其它两极阻值为无穷大,调换表笔后该极与其它两极的阻值仍为无穷大,则判断此极为栅极(G)。其余两极再用万用表测量,若测得阻值为无穷大,调换表笔后测量阻值较小。在测量阻值 ...…

查看全部问答>

很奇怪的问题 wince 串口测试应用程序 writefile(...)函数没有执行完就失败了,然后程序死掉了。

串口测试的writefile(...)函数没有执行完就失败了,没有任何返回结果。writefile的下一个语句做断点,没有执行到。 if(hComm!=INVALID_HANDLE_VALUE&&dwCharToWrite!=0)         {           &nbs ...…

查看全部问答>

终于研发成功

终于研发成功,cpu是s3c2410,64M   SDRAM,网口为cs8900 flash(k9f1208 64m)   实现了只用nand flash 就可以启动引导vxworks. 公司送bsp及全套开发文档 ,另可配公司的开发板 有意着QQ联系641328010 请注明 arm…

查看全部问答>

STC12LE5206AD 程序将引脚置为0 却检测到为高

有谁能够帮忙解决下啊? 本人qq:853887107…

查看全部问答>

RT_THREAD中的异常与中断

  异常是导致处理器脱离正常运行转向执行特殊代码的任何事件,如果系统不及时处理,系统轻则出错,重着导致系统毁灭性的瘫痪。所以正确地处理异常避免错误的发生是提高软件的鲁棒性重要的一方面,对于嵌入式系统更加如此。 异常可以分成两类 ...…

查看全部问答>

DIY导航避障车规整贴

DIY导航避障车小组今日下午展开第一次例会,在本次例会中大家集中讨论了无线的选择,避障的选择等等部分,并对小车进行了前景规划,以谷歌的自动驾驶车为终极目标,大家积极发言例会持续了一个半小时,并表示未来会采用各种新技术。下次再来把细节 ...…

查看全部问答>

11.06【每周讨论】软文——春风化雨、润物无声

您知道“软文”的含义吗?什么,不知道。赶紧百度一下吧,别被OUT了 [ 本帖最后由 longxtianya 于 2011-11-6 20:19 编辑 ]…

查看全部问答>

分享一些收集的msp430方面的书籍

最近接触了一下msp430的单片机从网上搜集了一些书籍希望对大家有帮助。…

查看全部问答>

泰克2012年度春季创新论坛北京站见闻

    4月24日阴雨天气,阿牛哥上午9点去北京朝阳区五洲皇冠大酒店参加泰克2012年度春季创新论坛。热情的工程师们朋友已经在会场里聆听泰克的测试测量行业趋势观点,泰克领先测试测量方案,还有一些工程师朋友在展厅参观泰克最新 ...…

查看全部问答>

全球智能机Q2出货1.5亿部 中兴进前五

本帖最后由 jameswangsynnex 于 2015-3-3 20:01 编辑 …

查看全部问答>