学习ARM开发10-19

 /***********************************
 *作者:蔡军生
 *出处:http://blog.csdn.net/caimouse/
 ************************************/
 学习ARM开发(10)

/* 用循环调用所有初始化函数 */
        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
        {
                if ((*init_fnc_ptr)() != 0)
                {
                        /* 当每个函数初始化失败时,就会挂机在这里。 */
                        hang();
                }
        }
上次说到在函数指针数组里,不断地调用所有初始化函数进行初始化,下面就来仔细地分析一下,它们到底是做什么的,做什么样的初始化,怎么样为后面做好运行的准备工作。看到第一个初始化函数,就是CPU初始化(cpu_init),这个函数是在cpu/s3c44b0/cpu.c里,它的作用就是进行S3C44B0初始化工作。看到这个函数内容如下:
/*
CPU初始化。
蔡军生 2005/07/23
*/
int cpu_init (void)
{
        /* 清空缓冲区 */
        icache_enable();

        return 0;
}

它在里面调用了函数icache_enable(),它就是用来初始化S3C44B0的缓冲区,并且启用CPU缓冲区。因为CPU在加电之后,它的初始化值是不启用内部的8K缓冲区的,必须由程序进行设置。接着看看那个调用的函数又是怎么样初始化内部缓存区的呢?
/*
CPU内存的缓冲初始化。
蔡军生 2005/07/23
*/
void icache_enable (void)
{
        ulong reg;

        /* 清空内存的缓冲区.  */
        s3c44b0_flush_cache();

        /*
                初始化缓冲区,
                设置非缓冲区的起始地址和结束地址。
                第一个寄存器指明下面的地址不要缓存,低16位是起始地址,
                高16位是结束地址。并且空间大小都是以4K为界。
                0x0000:0000 - 0x0C00:0000
         */
        NCACHBE0 = 0xC0000000;
        NCACHBE1 = 0x00000000;

        /*
                设置SYSCFG寄存器启用8K缓冲区。
        */
        reg = SYSCFG;
        reg |= 0x00000006; /* 8kB */
        SYSCFG = reg;
}

在这个函数里,第一个先调用函数是进行缓冲区清0的工作,它有一些特别的地方,如下:
/*
CPU的内部缓冲初始化。
蔡军生 2005/07/23
*/
static void s3c44b0_flush_cache(void)
{
        volatile int i;
        /* 清空缓冲区,每次要按4个32位来读写,所以要加16. */
        for( i = 0x10002000; i < 0x10004800; i += 16 )
        {
                *((int *)i)=0x0;
        }
}

它用一个for循环进行内部的缓冲区初始化,由于S3C44B0决定每次读写都是按16字节进行的。因此,这里的i就是不断地加16个字节。不过,这里为什么不清除0x10000000到0x10001fff区域呢?这个我也没有搞清楚,等我有空试试清除有没有问题!
到现在为止,缓冲区已经清空,就要设置那些内存区域是不要进行缓存的。因为不是所有内存都需要进行缓冲的,比如读取外面的IO,就不需要进行缓冲;读取FLASH也不需要。因此,设置第一个非缓冲区的起始地址为NCACHBE0 = 0xC0000000,这个值里的低16位是起始地址0x0000,它的32位地址就是从0x00000000开始。它的高16位是结束地址0Xc000,它的32位地址就是从0Xc0000000结束。最后就是通过设置SYSCFG寄存器的[2:1]位的值为11,就启用了8K内存数据和指令缓冲区。到这里为止,就已经设置好CPU的缓冲区初始化和启用。

学习ARM开发(11)

昨天又是星期天,在家里又可以对那块开发板进行软件研究了。
由于前几次,把编译好的UBOOT写到FLASH老是运行不了。那么怎么办呢?思考了很久,也查看

了源程序,还是没有发现问题。也许那个UBOOT的源程序太大,有很多的编译开关,还有很多驱

动程序选择,所以一头雾水,不知怎么办好。到了这个时候,只有从头开始跟踪了。就是尽可

能地跟踪程序运行到那里。
因而依次地进行下面的检查:
1. 检查设置的倍频是否对。
2. 检查程序写到FLASH的数据是否对。
3. 检查设置RAM是否对。
4. 检查设置串口的波特率是否对。

一般进行四部份检查就找出大体的问题。我首先查了一下,我的开发板上的晶振是10MHz输入,

那么我要倍频到60MHz,所以就要计算它的倍频系数。当然最快的办法,就是用三星提供的

PLLSET.EXE工具,五秒钟就搞定了。经过检查,发现我的倍频系数不对,所以重新设置倍频系

数。一般设置过倍频系后,都要调整串口波特率、SDRAM的刷新频率。设置好倍频系数后,接着

,就要计算串口的波特率,这个三星的S3C44B0的手册有计算公式。比如9600,就是拿60MHz进

行分频得到的。
这次设置好后这些东西之后,就把UBOOT编译后,再写到FLASH运行,还是不行。偶都在痛苦中

,为什么还不行呢。后来我想想,把UBOOT的编译地址改到0x00000000运行,就是在FLASH运行

,不拷贝到SDRAM中运行。结果是可以运行一段,串口有东西输出来,我的设置的LED也可以显

示。蜂鸣器也不响。说明这个串口的设置已经对,那么系统的倍频也对了。但UBOOT的堆栈我没

有改,所以只能跑到没有使用到堆栈的代码。
接着,我还需要改回到0x0C100000的基地址运行。经过用ADS中的AXD调试,单步跟踪。又是一

件痛苦的事情,发现AXD只能单步跟踪,设置断点,或者其它调试都不行,如果在后面设置了断

点,选择运行,发现到断点,还停不下来的。
呵呵。。。。。。。调试就是这样的,不是样样都顺手。既然只能单步运行,就老老实实地单

步调试了,经过30多分钟的单步运行,F8都已经按得手软。最后才跟踪到出错的地址,发现内

存设置不对。主要是SDRAM的设置不对,查看了加载地址的出错了。发现了这个加载地址出错,

偶也没有更好的办法解决之前,就只好把算好的值,依次地用ldr加载到r1-r13,共13个寄存器

里。接着让AXD全速运行,程序就可运行了。原来出错就是没有把SDRAM的参数加载正确,让我

调试了三天。
通过一个多小时的调试,串口可以显示了,UBOOT的很多命令也可运行了。但还没有调通USB口

,也没有网络接口。后面的工作,就是先调通网络接口。我的开发板用的网络芯片是RTL8019AS

,这个我也没有怎么看过,得好好找点资料,了解了解这个IC,然后找一份LINUX的RTL8019的

驱动程序出来看看,再决定怎么样调通RTL8019,由于RTL8019要用到中断,就要先检查S3C44B0

设置,否则到最后都没有办法调试。
通过开发板的调试,与SKYEYE相比,主要的区别是在SDRAM的频率,串口的频率,还有中断的功

能,都有很大的不同。因此,在SKYEYE上能运行的,在开发板,就不一定可以运行,就是这个

原因。

 学习ARM开发(12)
近来这段时间忙着开发USB的SKYPE电话,一直没有时间去开发ARM,这个星期天又有空在家里学习ARM开发了。

以前改写UBOOT已经改到可以启动了,并且可以运行到一段程序,在串口已经可以有输出的信息。但出现了一个很大的问题,就是malloc分配内存出错。当然我是使用arm-linux-gcc来编译的,不知道为什么它编译时不能初始化静态成员变量,就导致malloc分配内存的全局变量出错,出现了一个很大的值。经历好几天的调试,总算把malloc的内存分配返回0这个BUG解决了。解决方法,就是分配内存函数调用之前,就进行内存分配函数的初始化,这样就可以主动地初始化全局分配的变量,就可以解决malloc分配内存返回0的问题。

 并且由于对LINUX的深入了解,目前已经改变了以前FTP的共享方式,使用SAMB服务器共享文件,这样更加方便。只要在LINUX下共享这个目录,然后在WINDOWS下就可完全操作它,并且就像WINDOWS目录一样。这样就可以利用WINDWOS下好用的编辑器来编写程序,然后在LINUX下进行编译,然后又在那里把编译出来的程序直接下载到开发板上运行了。这样更加方便,更快速。

 学习ARM开发(13)
由于UBOOT大部份源程序已经修改好,目前就是修改网络部份了。由于网络设计,是采用了16位数据线的方式,还有RTL8019AS采用了9346的存储器,这样的设计都带来了很大的麻烦。因为是全新的东西,没有任何经验,也没有相应的仪器。所以开发这个RTL8019AS的网络驱动,就成为了一个很大的问题。

无论有多难,都要去面对的。要写RTL8019AS的驱动,首先的问题,就是找到S3C44B0访问RTL8019AS的寄存器,如果没有寄存器,就无法对它编程,也没有办法对它控制。那么它的寄存器地址是在那里呢?起先,我是从原理图上找到它的选片接线,是接到CPU的nGCS3上,那么它的地址肯定是从0X0600_0000开始了。接着看到我的RTL8019AS是16位的接线方式,那么它与CPU的连接方式是要从地址线1开始连接,因为S3C44B0对于8位,16位,32位的地址线输出是要求的。这样就可以算出RTL8019AS的地址是0x0600_0000再加上寄存器址左移一位,因为地址线0是不用的,只有1到5在使用。比如复位寄存器地址就是0x0600_0000+(0x1F<<1),这样就可以找到所有寄存器地址了。

地址找到了,那么我就要对它进访问。由于嵌入式的CPU是内存地址与寄存器地址是统一编址的,因此直接访问就行了。刚开始,我直接写寄存器,和读取寄器,发现数据全部都是0XFF,这显然是不对的。就当我修改为其它值,再读出来,都是0XFF,说明寄存器不响应。这时,我不知道是什么原因引起的。接着为了寻找这个问题,就找了一堆资料,结果都找不到。然后又查看硬件,又查找软件。都没有发现有什么问题,实在没有办法了。看到别人的板都没有9346这个存储器,是不是我的存储器有问题?我也搞不懂它。后来就把它拔下来,接着再试还是不行。读取寄存器,还是0XFF值。接着再查看RTL8019AS的DATASHEET,发现65脚跳线也是一个问题。我查看一下我的接线是接了一个电阻,然后再接到VDD上。我试着把这个电阻断开,让它是低电平。

后来一试,果然读写寄存器的值变了,不是0XFF了。说明这些寄存器有效了。

 学习ARM开发(14)
由于在LINUX下开发还是比较麻烦,那么在WINDOWS下有没有更加方便简单的开发方法呢?答案是肯定的。当然不是选择ADS这样的开发工具,因为它成本太贵。就算使用盗版,也不会觉得心安理得,那么就要采用其它方案了。目前只有选择GCC的开发工具。经过不断地努力,总找到合适的ARM开发工具。它就是WINARM,采用它来开发,就大提高了工作效率,使写起代码来更加方便,编译更加快速,出错更容易修改,并且比较便宜,又可作为商业使用。

采用GCC编译器后,编译程序发了一个警告,它如下:

init.h 13:29: warning: no newline at end of file

这个出错的意思,就是在文件尾没有结束行。这个东东是什么呢?通过GOOGLE查找,总算找到了合算的解答了。因为C++ ISO里定义一个文件结束一定需要新行结尾的。跟我们在VC中写的程序是有点差别吧,在VC里不用在文件最后一行添加空行的,但GCC是一定需要的,因为它是解决一个文件与另一个文件连接的问题。

因此只要在文件后尾新起一行,就解决这个BUG了。

 学习ARM开发(15)
使用GCC来开发ARM,就一定遇到编译器的问题。比如遇到编译C代码各种警告和错误。像我昨天就遇到了几个警告,那么就来看看这几个警告是什么引导的呢?

警告如下:

armlib/memory.c: 91 warning: cast increases required alignment of target type

这个警告是什么意思呢?从字面上来看,就是类型转换时,引起目标类型的存储方式排列改变。比如从一个char*指针转换为一个int*指针,就出这样的警告。比如:

char* pTest1;

int* pTest2;

pTest = (int*)pTest1;

这种转换就会有警告出现。

当然这种警告是设置了GCC的-Wcast-align 编译参数才会出现的。这种警告,就提示了不同的类型强制转换,会导致字节排列顺序的改变的危险。

 学习ARM开发(16)
ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进

入多任务系统工作,并且大大提高了工作效率。采用中断比以往的查询方式占用更少的CPU时间,让

系统提供更好性能。那么中断在S3C44B0中是怎么样的呢?在开发ARM程序中是怎么样进行响应的呢

?这就是我需要学习的东西。
查询S3C44B0的手册,发现它有7种工作模式,每种工作模式是不一样的。其中最常用的,就是SVC和

IRQ模式。在使用中断之前,一定要初始化每种模式的栈指针SP,如果不初始化,肯定会出错。在CP

U进行初始化时,就需要依次进入IRQ模式,初始化SP,接着再进入SVC模式初始化SP。这样这两种模

式,就可以使用了。然后再在S3C44B0的中断向表里,初始化IRQ的中断处理程序,这段代码就是用

来根据不同中断位来调用不同的中断子程序。
对于使用C语言写的中断子程序,一定要加一些特定的修饰定义,否则C编译器不会生成适合中断模

式下运行的程序。由于我对GCC不是很了解,就调试了好几天,才发现我写的中断处理程序没有返回

去,原因就是没有加这些中断修饰定义,GCC编译器就没有生成合适返回指令。当我加了如下:

void Eint4567Isr(void) __attribute__ ((interrupt ("IRQ")));

的修改之后,就会生成合适的中断处理程序了。GCC就会编译成这样的代码:
sub lr, lr, #4 ;
stmdb sp!, {r0, r1, r2, r3, r4, ip, lr}
......
......
ldmia sp!, {r0, r1, r2, r3, r4, ip, pc}^

由于从IRQ模式返回到SVC模式,就需要把LR减4,才是PC的指令。如果不加上面的中断修饰定义,就

不会生成这样的代码,这样的函数就不能作来中断处理使用。
当然,我也是通过编译出这些的代码之后,再反汇编之后,然后发现不一样的。然后通过嵌入式汇

编也是可以实现的。比如:
void foo(void)
{
  asm volatile ( "sub lr, lr, #4" );
  asm volatile ( "stmdb sp!, {r0, r1, r2, r3, r4, ip, lr}" );
......
......

  asm volatile ( "ldmia sp!, {r0, r1, r2, r3, r4, ip, pc}" );
  return;
}

原先,在我没有找到这个定义之前,就是通过自己手动地添加上面的代码实现的。这段中断代码,

让我学会了怎么样处理中断,从SVC到IRQ模式,然后再从IRQ模式转回到SVC模式。只要从LR移动到P

C,就自己转回到SVC的模式了。

 通过查找GCC的帮助文档,下面的连接:

http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html,就可看到中断函数在GCC的里声明。

5.24 Declaring Attributes of Functions
In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully.

The keyword __attribute__ allows you to specify special attributes when making a declaration. This keyword is followed by an attribute specification inside double parentheses. The following attributes are currently defined for functions on all targets: noreturn, noinline, always_inline, pure, const, nothrow, sentinel, format, format_arg, no_instrument_function, section, constructor, destructor, used, unused, deprecated, weak, malloc, alias, warn_unused_result and nonnull. Several other attributes are defined for functions on particular target systems. Other attributes, including section are supported for variables declarations (see Variable Attributes) and for types (see Type Attributes).

You may also specify attributes with `__' preceding and following each keyword. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use __noreturn__ instead of noreturn.

See Attribute Syntax, for details of the exact syntax for using attributes.

然后再看看它的中断函数声明:

interrupt
Use this attribute on the ARM, AVR, C4x, M32R/D and Xstormy16 ports to indicate that the specified function is an interrupt handler. The compiler will generate function entry and exit sequences suitable for use in an interrupt handler when this attribute is present.
Note, interrupt handlers for the m68k, H8/300, H8/300H, H8S, and SH processors can be specified via the interrupt_handler attribute.

Note, on the AVR, interrupts will be enabled inside the function.

Note, for the ARM, you can specify the kind of interrupt to be handled by adding an optional parameter to the interrupt attribute like this:

          void f () __attribute__ ((interrupt ("IRQ")));    
Permissible values for this parameter are: IRQ, FIQ, SWI, ABORT and UNDEF.


除了可以使用IRQ中断方式之外,还可以写FIQ,SWI,ABORT,UNDEF的中断处理函数。

 学习ARM开发(17)
因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深

入了解,最好的方法,就是去写程序,然后不断地调试。在这个程序之前,先要深入去了解ARM的中断方式,知

道它有7种工作方式。下面先看初始化的代码是怎么样初始化不同模式栈的。
/*  IRQMODE。  */   
orr     r1,r0,#0x12|0xc0
msr     cpsr,r1 
ldr     sp,=IRQ_MODE_SP_START

这段代码,就是初始化IRQ模式的栈,这样在IRQ中断时就可以使用栈了。

S3C44B0的中断过运行过程是这样的:
当有中断发生时,就会跳到FLASH中的地址0x18处理取到一条指令并执行,因为那里只允许放一条指令,因此只

能放一条跳转指令了。比如:ldr pc,=0x0c000018  ,这条指令就是跳到SDRAM里运行,意思从0x0c000018取一

条指令运行,其实我总是在那地址里放一条跳转指令的,这样又到相应的中断处理程序了。比如在那里一条:
b irq,这条指令就是跳到IRQ的中断处理程序运行,它的作用就是根据不同的中断源来进一步查找不同的

中断处理程序。它的代码如下:
/*
采用IRQ中断,查找各个中断的入口函数地址,并且跳到相应的入口函数运行。 蔡军生  2006/02/10
*/

irq:sub     sp,sp,#4       /* 保留一个栈给PC */
    stmfd   sp!,{r8-r9}  
 
    ldr     r9,=I_ISPR    /* 读取中断源寄存器 */
    ldr     r9,[r9]

    cmp  r9, #0x0 /* 如果没有中断源发生,就退出去。 */
    beq  IDLE_IRQ
 
    mov     r8,#0x0    /* 计算中断源对应的中断程序位置  */
LOOP_IRQ:
    movs    r9,r9,lsr #1
    bcs     HAVE_IRQ
    add     r8,r8,#4   /* 每个中断入口占4个字节 */
    b     LOOP_IRQ

HAVE_IRQ:
    ldr     r9,=CONFIG_SDRAM_START+4*8  /* 从HandleADC中断入口  */
    add     r9,r9,r8
    ldr     r9,[r9]
    str     r9,[sp,#8]           /* 保存到前面保留的SP位置 */
       
    ldmfd   sp!,{r8-r9,pc}      /* 跳到中断程序运行.  */

IDLE_IRQ:                       /* 没有中断处理。 */
 ldmfd sp!,{r8-r9}
 add sp,sp,#4
 subs pc,lr,#4

这段代码的功能就是先从S3C44B0的中断源保存寄存器I_ISPR取出中断源的标识位,然后不断移位,判断这位是

否有中断,如果有中断就处理它。根据移位来算出它的中断入口地址在那里,这样的做法,就可以动态地改变中

断入口函数。CONFIG_SDRAM_START+4*8,这个就是中断入口函数基地址,如果是第一位有中断,就是ADC中断。

那么就直接跳到这个地址运行就OK了。
比如我使用S3C44B0的TICK中断,就是时间片中断。就会在相应的地址设置入口函数,使用如下代码:
///
//函数名称:   TickInstall
//函数功能:   安装Tick中断函数。
//输入参数:
//输出参数:
//返 回 值:   
//开发人员:   蔡军生
//时    间:   2006/02/13
//修改说明:  
//
///
void TickInstall(unsigned int nTickFunc)
{
 //
 *((unsigned int *)(INT_ADDR_START + 20*4)) = nTickFunc;
}

上面语句就是把一个中断入口函数设置为时间片运行函数。当有TICK中断时,就会跑到时间片函数里运行了。
总结一下,写一个S3C44B0的中断处理需要做以下几部分工作:

1. 在FLASH里0x18处放一条跳转指令,跳到SDRAM里运行。
2. 在SDRAM里0x0c000018处,放一条跳转指令,跳到IRQ子程序运行。
3. 写一段IRQ处理程序。
4. 写一段处理实际中断源的处理函数。
5. 设置中断寄存器,清除中断源屏蔽位。


 学习ARM开发(18)
上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中断是否打开的。 这几个寄存器如下:

1. 程序状态寄存器(CPSR).

这个寄存器里有两位可以控制是否响应FIQ或IRQ中断的设置。如果把这两位全部置1,就全部不响应中断了。后面会用到这两位来关中断的,在RTOS里就需要使用到这两位关中断作为临界区。

2. 中断控制寄存器(INTCON)

这个寄存器只使用到低3位:0,1,2。
第0位设置为1时,不使用FIQ的中断;设置为0时,就是使用FIQ的中断。
第1位设置为1时,不使用IRQ的中断;设置为0时,就是使用IRQ的中断。
第2位设置为1时,使用非向量的方式IRQ中断,设置为0时使用向量方式IRQ中断。

3. 中断模式寄存器(INTMOD)

这个寄存器设置26个中断源使用中断的方式。当相应位设置为0时,就表示使用IRQ中断方式,当相应位设置为1时,就表示使用FIQ的中断方式。

4. 中断屏蔽寄存器(INTMSK)

这个寄存器是用来指定那位可以响应中断的。其中第26位比较特别的,它是全局中断屏蔽位。如果设置它为1,就全部中断都不响应了。0到25位就是26个中断源的屏蔽位,如果设置为1,就表示不响应中断,设置为0就表示响应中断。

5. 清除中断位寄存器(I_ISPC)

当中断发生之后,还想再次发生中断。那么就需要清除相应的中断位,这时就使用I_ISPC中断寄存器。
当设置这个寄存器相应位为1时,就清除了相应的中断位,下一个中断到来时,就可以再次响应了。

通过设置上面几个中断寄存器,就可以让S3C44B0的中断工作了。中断是非常重要的,一定要熟练地使用。不管什么样的CPU,都是使用这样的东西。中断是现代高速CPU与低速设备之间对话的机制,没有这个机制,就根本不能让高速的CPU高效地工作了。

 学习ARM开发(19)
使用TICK中断

经过许多天的努力,总算可以使用中断了,但为了让RTOS可以使用定时中断,那么在S3C44B0里有什么样的中断可以实现呢?在S3C44B0里有两种方法可以实现这样中断,一种是通过定时器中断,一种是通RTC的TICK定时中断。由于S3C44B0片内已经有提供给RTOS的中断,就应使用它作为RTOS的中断,这样可以使时间片跟RTC时钟是时间同步。RTOS调度任务是通过设置时间片中断实现的。当时间片到达时,就向CPU发出中断信号,CPU就会把当前任务状态保存下来,然后转到中断进程运行,并且在中断里放着的是进行优先选择运行任务的程序,接着从中断返回时就可以运行不同的任务了。既然这个中断那么重要,就需要详细地了解TICK中断实现。

S3C44B0的内部有一个实时日历时钟(RTC)单元,它只需要外接一个32.768kHz的晶振即可工作。当然要对它进行编程初始化才能工作的,下面就来看看是怎么样初始化的。

首先,通过RTCCON寄存器的第0位来表示要“读”还是“写”RTC的寄存器。当设置第0位为1时,就允许读写所有寄存器。当设置第0位为0时,就只允许读,不允许写所有寄存器。

其次,通过TICNT寄存器来控制产生TICK中断。这个寄存器的第7位是表示是否启用TICK中断。当启用时,就设置为1。第0到6位表示中断计数值,要多久才中断,是通过下面的公式计算得到的:

时间片 = (n+1)/128 秒,

其中n是需要设置的数值,它的范围是从1到127。

从上面的公式可以看出来,当设置n值越大时,时间片就越大,当设置为127时,就时一秒钟中断一次了。设置为最小值1时,就是15.625ms。

最后,下面这段程序就是设置TICK中断,这样就要以供RTOS使用了。

///
//函数名称:   TickIntEnable
//函数功能:   打开Tick中断。
//输入参数:   nTickCount---分频系数。
//输出参数:
//返 回 值:   
//开发人员:   蔡军生
//时    间:   2006/02/13
//修改说明:  
//
///

void TickIntEnable(unsigned int nTickCount)

{
  //  
  I_ISPC |= (unsigned int)0x01 << 20;

  //

  //清除屏蔽位。

  INTMSK &= ~(BIT_GLOBAL|BIT_TICK);

 
  RTCCON = (unsigned char)1;

  TICINT = (unsigned char)(nTickCount | 0x80);

  RTCCON = (unsigned char)0;

 

}


如果中断寄存器已经设置好,那么这个RTOS的时间片中断,就已经可以工作了。接着最重要的工作,就是怎么样在中断子程序里进行RTOS的任务切换,这个比较复杂,需要很长时间去了解和实验,并且要对ARM的汇编比较好。这个时间片设置长短,也跟不同的应用有关系的,如果需要快速实时的中断,就需要设置它短一点,这样检查任务切换就及时一点,但也有一个坏处,就是浪费在任务切换上的CPU资源比较多。如果任务调试不需要太及时,就可以设置大一点,这样浪费在任务切换上的CPU资源就减少了。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值