zoukankan      html  css  js  c++  java
  • 第二讲 硬件I/O操作

    **********************
    * 第二讲 硬件I/O操作 *
    **********************
        对设备进行访问和控制时需要访问I/O寄存器。硬件抽象层提供了一些宏用于I/O寄存器的读写操作。
        之所以不用指针直接操作,目的是为了可移植性。使用宏的原因是避免函数调用引起的性能损失。ecos是一种可移植的嵌入式操作系统,它可以移植到16位、32位、64位的各种处理器平台上。ecos由各种组件构成,根据具体硬件平台的需要可以分别将这些组件加入到系统中来,从而实现各种所需的功能。ecos的这种层次结构的最底层是硬件抽象层(Hardware Abstraction Layer),通常称为HAL。硬件抽象层HAL对处理器结构和系统硬件平台进行抽象,当需要在一个新的目标平台上运行ecos时,只需对底层的硬件抽象层进行修改,便可迅速地将整个ecos系统移植到新的平台上。
        常用I/O操作宏:
        读寄存器值  从寄存器读数据并将结果存放在存值变量里
        HAL_READ_UINT8(寄存器地址,存值变量);
        HAL_READ_UINT16(寄存器地址,存值变量);
        HAL_READ_UINT32(寄存器地址,存值变量);
        写寄存器  向寄存器写如数值
        HAL_WRITE_UINT8(寄存器地址,值);
        HAL_WRITE_UINT16(寄存器地址,值);
        HAL_WRITE_UINT32(寄存器地址,值);
        这些宏位于头文件cyg/hal/hal_io.h内,感兴趣的读者可以看看这些宏是怎么实现的。
        I/O操作宏的定义也是按照ecos的分层原则定义的,HAL表示这是硬件抽象层函数,READ/WRITE表示具体操作,UINTx表示读写宽度,这些宏很容易记忆的,而且见名知意。
    寄存器名称定义在cyg/hal/plf_io.h中,我们仍然按照ecos命名规则起名,如下:
    // GPIO
    #define LPC2XXX_GPIO_IO0PIN       0xE0028000
    #define LPC2XXX_GPIO_IO0SET       0xE0028004
    #define LPC2XXX_GPIO_IO0DIR       0xE0028008
    #define LPC2XXX_GPIO_IO0CLR       0xE002800C
        LPC2XXX表示芯片型号,GPIO表示I/O类型,IO-n-ops表示Pn口的操作方式(引脚、方向、设置、清除)。这样的命名比枯燥的数字更容易记忆,不重名也不易错。
        下面是控制GPIO让蜂鸣器发声的应用程序,响1秒停1秒,周而复始。线程创建第一讲已经说过,不再重复。
    #i nclude <cyg/kernel/kapi.h>
    #i nclude <cyg/hal/hal_io.h>
    #i nclude <cyg/hal/plf_io.h>
    #define STACK_SIZE 4096
    #define BEEPCON 0x0000080
    char stack[2][STACK_SIZE];
    static cyg_thread thread_data[2];
    static cyg_handle_t thread_handle[2];
    void taska(cyg_addrword_t data)
    {
        int message = (int) data;
        HAL_WRITE_UINT32(LPC2XXX_GPIO_IO0DIR,BEEPCON);
        for(;;)
        {
            HAL_WRITE_UINT32(LPC2XXX_GPIO_IO0SET,BEEPCON);
            cyg_thread_delay(100);
            HAL_WRITE_UINT32(LPC2XXX_GPIO_IO0CLR,BEEPCON);
            cyg_thread_delay(100);
        }
    }
    void
    test(cyg_addrword_t data)
    {
        printf("\n\n\n");
        printf("\t    *******************************\n");
        printf("\t    *     Hello! The world.       *\n");
        printf("\t    *******************************\n\n\n");
        // Create a main thread, so we can run the scheduler and have time 'pass'
        cyg_thread_create(10,                // Priority - just a number
                          taska,             // entry
                          1,                 // entry parameter
                          "taska",           // Name
                          &stack[1],         // Stack
                          STACK_SIZE,        // Size
                          &thread_handle[1], // Handle
                          &thread_data[1]    // Thread data structure
                );
        cyg_thread_resume(thread_handle[1]); // Start it
    }
    void
    cyg_start(void)
    {
        // Create a main thread, so we can run the scheduler and have time 'pass'
        cyg_thread_create(10,                // Priority - just a number
                          test,              // entry
                          0,                 // entry parameter
                          "test",            // Name
                          &stack[0],         // Stack
                          STACK_SIZE,        // Size
                          &thread_handle[0], // Handle
                          &thread_data[0]    // Thread data structure
                );
        cyg_thread_resume(thread_handle[0]); // Start it
        cyg_scheduler_start();
    }

  • 相关阅读:
    人为什么会生气 --- 答案是什么?
    职场中我们常犯的8个错误
    职场上最常见的20条错误,犯三条就够致命啦
    C语言,基于单向链表实现,变长动态数据缓冲区(线程安全) ---- 类似java的StringBuffer --- 亲测OK
    门限签名
    基于RSA的实用门限签名算法
    图解密码技术(第3版)-第4章
    各种加密算法比较
    密码那点事儿
    数字签名,我有疑问。
  • 原文地址:https://www.cnblogs.com/kuainiao/p/2854936.html
Copyright © 2011-2022 走看看