新闻  |   论坛  |   博客  |   在线研讨会
RT_Thread IoT_Board笔记2:LED闪烁例程_通用GPIO设备
电子禅石 | 2018-12-27 10:09:14    阅读:11264   发布文章
参考内容:通用GPIO设备应用笔记
https://www.rt-thread.org/document/site/rtthread-application-note/driver/gpio/an0002-rtthread-driver-gpio/

问题:#define LED_PIN             PIN_LED_R   io口是如何一一对应起来的。

在drv_gpio.c文件中 列出了100个引脚的对应关系还有中断的相关关系。
static const struct pin_index pins[] =
{
   __STM32_PIN_DEFAULT,
   __STM32_PIN(1, E, 2),       // PE2:  SAI1_MCLK_A  --> ES8388
   __STM32_PIN(2, E, 3),       // PE3:  SAI1_SD_B    --> ES8388
   __STM32_PIN(3, E, 4),       // PE4:  SAI1_FS_A    --> ES8388
   __STM32_PIN(4, E, 5),       // PE5:  SAI1_SCK_A   --> ES8388
   __STM32_PIN(5, E, 6),       // PE6:  SAI1_SD_A    --> ES8388
   __STM32_PIN_DEFAULT,        //     : VBAT
   __STM32_PIN(7, C, 13),      //PC13:  SD_CS        --> SD_CARD
   __STM32_PIN(8, C, 14),      //PC14:  OSC32_IN
   __STM32_PIN(9, C, 15),      //PC15:  OSC32_OUT
   __STM32_PIN_DEFAULT,       //     :  VSS
   __STM32_PIN_DEFAULT,        //    :  VDD
   __STM32_PIN_DEFAULT,        // PH0:  OSC_IN
   __STM32_PIN_DEFAULT,        // PH1:  OSC_OUT
   __STM32_PIN_DEFAULT,       //     :  RESET
   __STM32_PIN(15, C, 0),      // PC0:  I2C_SCL      --> ES8388
   __STM32_PIN(16, C, 1),      // PC1:  I2C_SDA      --> ES8388
   __STM32_PIN(17, C, 2),      // PC2:  GBC_LED      --> ATK MODULE
   __STM32_PIN(18, C, 3),      // PC3:  GBC_KEY      --> ATK MODULE
   __STM32_PIN_DEFAULT,       //     :  VSSA
   __STM32_PIN_DEFAULT,        //    :  VREF-
   __STM32_PIN_DEFAULT,       //     :  VREF+
   __STM32_PIN_DEFAULT,       //     :  VDDA
   __STM32_PIN(23, A, 0),      // PA0:  MOTOR_A      --> MOTOR
   __STM32_PIN(24, A, 1),      // PA1:  MOTOR_B      --> MOTOR
   __STM32_PIN(25, A, 2),      // PA2:  UART2_TX     --> EXTERNAL MODULE
   __STM32_PIN(26, A, 3),      // PA3:  UART2_RX     --> EXTERNAL MODULE
   __STM32_PIN_DEFAULT,       //     :  VSS
   __STM32_PIN_DEFAULT,       //     :  VDD
   __STM32_PIN(29, A, 4),      // PA4:  ADC12_IN9    --> EXTERNAL MODULE
   __STM32_PIN(30, A, 5),      // PA5:  SPI1_SCK     --> SD_CARD
   __STM32_PIN(31, A, 6),      // PA6:  SPI1_MISO    --> SD_CARD
   __STM32_PIN(32, A, 7),      // PA7:  SPI1_MOSI    --> SD_CARD
   __STM32_PIN(33, C, 4),      // PC4:  GBC_RX       --> ATK MODULE
   __STM32_PIN(34, C, 5),      // PC5:  WIFI_INT     --> WIFI
   __STM32_PIN(35, B, 0),      // PB0:  EMISSION     --> INFRARED EMISSION
   __STM32_PIN(36, B, 1),      // PB1:  RECEPTION    --> INFRARED EMISSION
   __STM32_PIN(37, B, 2),      // PB2:  BEEP         --> BEEP
   __STM32_PIN(38, E, 7),      // PE7:  LED_R        --> LED
   __STM32_PIN(39, E, 8),      // PE8:  LED_G        --> LED
   __STM32_PIN(40, E, 9),      // PE9:  LED_B        --> LED
   __STM32_PIN(41, E, 10),     //PE10:  QSPI_BK1_CLK --> SPI_FLASH
   __STM32_PIN(42, E, 11),     //PE11:  QSPI_BK1_NCS --> SPI_FLASH
   __STM32_PIN(43, E, 12),     //PE12:  QSPI_BK1_IO0 --> SPI_FLASH
   __STM32_PIN(44, E, 13),     //PE13:  QSPI_BK1_IO1 --> SPI_FLASH
   __STM32_PIN(45, E, 14),     //PE14:  QSPI_BK1_IO2 --> SPI_FLASH
   __STM32_PIN(46, E, 15),     //PE15:  QSPI_BK1_IO3 --> SPI_FLASH
   __STM32_PIN(47, B, 10),     //PB10:  AP_INT       --> ALS&PS SENSOR
   __STM32_PIN(48, B, 11),     //PB11:  ICM_INT      --> AXIS SENSOR
   __STM32_PIN_DEFAULT,       //     :  VSS
   __STM32_PIN_DEFAULT,       //     :  VDD
   __STM32_PIN(51, B, 12),     //PB12:  SPI2_CS      --> EXTERNAL MODULE
   __STM32_PIN(52, B, 13),     //PB13:  SPI2_SCK     --> EXTERNAL MODULE
   __STM32_PIN(53, B, 14),     //PB14:  SPI2_MISO    --> EXTERNAL MODULE
   __STM32_PIN(54, B, 15),     //PB15:  SPI2_MOSI    --> EXTERNAL MODULE
   __STM32_PIN(55, D, 8),      // PD8:  KEY0         --> KEY
   __STM32_PIN(56, D, 9),      // PD9:  KEY1         --> KEY
   __STM32_PIN(57, D, 10),     //PD10:  KEY2         --> KEY
   __STM32_PIN(58, D, 11),     //PD11:  WK_UP        --> KEY
   __STM32_PIN(59, D, 12),     //PD12:  IO_PD12      --> EXTERNAL MODULEL
   __STM32_PIN(60, D, 13),     //PD13:  IO_PD13      --> EXTERNAL MODULE
   __STM32_PIN(61, D, 14),     //PD14:  IO_PD14      --> EXTERNAL MODULE
   __STM32_PIN(62, D, 15),     //PD15:  IO_PD15      --> EXTERNAL MODULE
   __STM32_PIN(63, C, 6),      // PC6:  TIM3_CH1     --> EXTERNAL MODULE
   __STM32_PIN(64, C, 7),      // PC7:  TIM3_CH2     --> EXTERNAL MODULE
   __STM32_PIN(65, C, 8),      // PC8:  SDIO_D0      --> WIFI
   __STM32_PIN(66, C, 9),      // PC9:  SDIO_D1      --> WIFI
   __STM32_PIN(67, A, 8),      // PA8:  IO_PA8       --> EXTERNAL MODULE
   __STM32_PIN(68, A, 9),      // PA9:  UART1_TX     --> STLINK_RX
   __STM32_PIN(69, A, 10),     //PA10:  UART1_RX     --> STLINK_RX
    __STM32_PIN(70,A, 11),     // PA11:  USB_D-      --> USB OTG && EXTERNAL MODULE
   __STM32_PIN(71, A, 12),     //PA12:  USB_D+       --> USB OTG && EXTERNALMODULE
   __STM32_PIN(72, A, 13),     //PA13:  T_JTMS       --> STLINK
   __STM32_PIN_DEFAULT,       //     :  VDDUSB
   __STM32_PIN_DEFAULT,       //     :  VSS
   __STM32_PIN_DEFAULT,       //     :  VDD
   __STM32_PIN(76, A, 14),     //PA14:  T_JTCK       --> STLINK
   __STM32_PIN(77, A, 15),     //PA15:  AUDIO_PWR    --> AUDIO && POWER
   __STM32_PIN(78, C, 10),     //PC10:  SDIO_D2      --> WIFI
   __STM32_PIN(79, C, 11),     //PC11:  SDIO_D3      --> WIFI
   __STM32_PIN(80, C, 12),     //PC12:  SDIO_CLK     --> WIFI
   __STM32_PIN(81, D, 0),      //
   __STM32_PIN(82, D, 1),      // PD1:  WIFI_REG_ON  --> WIFI
   __STM32_PIN(83, D, 2),      // PD2:  SDIO_CMD     --> WIFI
   __STM32_PIN(84, D, 3),      // PD3:  IO_PD3       --> EXTERNAL MODULE
   __STM32_PIN(85, D, 4),      // PD4:  NRF_IRQ      --> WIRELESS
   __STM32_PIN(86, D, 5),      // PD5:  NRF_CE       --> WIRELESS
   __STM32_PIN(87, D, 6),      // PD6:  NRF_CS       --> WIRELESS
   __STM32_PIN(88, D, 7),      // PD7:  LCD_CS       --> LCD
   __STM32_PIN(89, B, 3),      // PB3:  LCD_SPI_SCK  --> LCD
   __STM32_PIN(90, B, 4),      // PB4:  LCD_WR       --> LCD
   __STM32_PIN(91, B, 5),      // PB5:  LCD_SPI_SDA  --> LCD
   __STM32_PIN(92, B, 6),      // PB6:  LCD_RESET    --> LCD
   __STM32_PIN(93, B, 7),      // PB7:  LCD_PWR      --> LCD
    __STM32_PIN_DEFAULT,        //    :  BOOT0
   __STM32_PIN(95, B, 8),      // PB8:  I2C1_SCL     --> EXTERNAL MODULE
   __STM32_PIN(96, B, 9),      // PB9:  I2C1_SDA     --> EXTERNAL MODULE
   __STM32_PIN(97, E, 0),      // PE0:  IO_PE0       --> EXTERNAL MODULE
   __STM32_PIN(98, E, 1),      // PE1:  IO_PE1       --> EXTERNAL MODULE
   __STM32_PIN_DEFAULT,       //     :  VSS
   __STM32_PIN_DEFAULT,       //     :  VDD
};
注册初始化
int rt_hw_pin_init(void)
{
   return rt_device_pin_register("pin", &_stm32_pin_ops,RT_NULL);
}
const static struct rt_pin_ops_stm32_pin_ops =
{
   stm32_pin_mode,
   stm32_pin_write,
   stm32_pin_read,
   stm32_pin_attach_irq,
   stm32_pin_dettach_irq,
   stm32_pin_irq_enable,
};

IO设备管理框架与通用GPIO设备的联系

RT-Thread 提供了一套简单的I/O 设备管理框架,它把 I/O 设备分成了三层进行处理:应用层、I/O 设备管理层、硬件驱动层。应用程序通过 RT-Thread 的设备操作接口获得正确的设备驱动,然后通过这个设备驱动与底层 I/O 硬件设备进行数据(或控制)交互。RT-Thread 提供给上层应用的是一个抽象的设备操作接口,给下层设备提供的是底层驱动框架。对于通用 GPIO 设备,应用程序既可以通过设备操作接口访问,又可以直接通过通用 GPIO 设备驱动来访问。一般来说,我们都是使用第二种方式。那么如何在 RT-Thread 中使用通用 GPIO 设备驱动从而操作 GPIO 呢?
RT-Thread 自动初始化功能依次调用 rt_hw_pin_init ===> rt_device_pin_register ===>rt_device_register 完成了 GPIO 硬件初始化。rt_device_register 注册设备类型为RT_Device_Class_Miscellaneous,即杂类设备,从而我们就可以使用统一的 API 操作 GPIO。
1.png 

程序运行流程怎么一步一步开始的?

在rtconfig.h中 配置使用PIN设备。
/* Kernel Device Object */
#define RT_USING_DEVICE
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 256
#define RT_CONSOLE_DEVICE_NAME"uart1"
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN           启动方式之一
#define RT_MAIN_THREAD_STACK_SIZE 2048
#define RT_MAIN_THREAD_PRIORITY 10
/* Device Drivers */
#define RT_USING_DEVICE_IPC
#define RT_PIPE_BUFSZ 512
#define RT_USING_SERIAL
#define RT_USING_PIN
都在components.c中,
从startup_stm32l475xx.s 启动文件中开始。
; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
       IMPORT  SystemInit   //系统初始化,时钟相关等
       IMPORT  __main
                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP
; Dummy Exception Handlers (infinite loopswhich can be modified)
由于rtconfig.h配置宏RT_USING_USER_MAIN,表明通过组件的方式跳到main函数,不过此时过程是,先重新定义main函数int $Sub$$main(void),代码先跳到int$Sub$$main(void)执行,
调用rt_application_init();创建main线程,在main线程中调用main函数
详见:components.c中:
#if defined(__CC_ARM) ||defined(__CLANG_ARM)
extern int $Super$$main(void);
/* re-define main function */
int $Sub$$main(void)
{
   rt_hw_interrupt_disable();
   rtthread_startup();//启动rtos.
   return 0;
}
int rtthread_startup(void)
{
   rt_hw_interrupt_disable();
   /* board level initialization
    * NOTE: please initialize heap inside board initialization.
    */
    rt_hw_board_init();//这里会进行rt_hw_pin_init()stm32_hw_usart_init();注册IO 串口设备
   /* show RT-Thread version */
   rt_show_version();
   /* timer system initialization */
   rt_system_timer_init();
   /* scheduler system initialization */
   rt_system_scheduler_init();
#ifdef RT_USING_SIGNALS
   /* signal system initialization */
   rt_system_signal_init();
#endif
   /* create init_thread */
    rt_application_init();//在这里创建main.c 的入口函数。
   /* timer thread initialization */
   rt_system_timer_thread_init();
   /* idle thread initialization */
   rt_thread_idle_init();
#ifdef RT_USING_SMP
   rt_hw_spin_lock(&_cpus_lock);
#endif /*RT_USING_SMP*/
   /* start scheduler */
   rt_system_scheduler_start();
   /* never reach here */
   return 0;
}
void rt_application_init(void)
{
   rt_thread_t tid;
#ifdef RT_USING_HEAP
   tid = rt_thread_create("main", main_thread_entry, RT_NULL,
                          RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
   RT_ASSERT(tid != RT_NULL);
#else
   rt_err_t result;
   tid = &main_thread;
   result = rt_thread_init(tid, "main", main_thread_entry,RT_NULL,
                           main_stack,sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
   RT_ASSERT(result == RT_EOK);
      
   /* if not define RT_USING_HEAP, using to eliminate the warning */
   (void)result;
#endif
    rt_thread_startup(tid);//启动这个线程。
}
/* the system main thread */
void main_thread_entry(void *parameter)
{
   extern int main(void);
   extern int $Super$$main(void);
   /* RT-Thread components initialization */
    rt_components_init();//组件初始化,这个例程暂时没用到。
#ifdef RT_USING_SMP
   rt_hw_secondary_cpu_up();
#endif
   /* invoke system main function */
#if defined(__CC_ARM) ||defined(__CLANG_ARM)
    $Super$$main(); /* for ARMCC. */转到main.c中
#elif defined(__ICCARM__) ||defined(__GNUC__)
   main();
#endif
}
由于定义#define RT_USING_COMPONENTS_INIT
/*
*Components Initialization will initialize some driver and components asfollowing
*order:
*rti_start         --> 0
*BOARD_EXPORT      --> 1
*rti_board_end     --> 1.end
*
*DEVICE_EXPORT     --> 2
*COMPONENT_EXPORT  --> 3
*FS_EXPORT         --> 4
*ENV_EXPORT        --> 5
*APP_EXPORT        --> 6
*
*rti_end           --> 6.end
*
*These automatically initialization, the driver or component initial functionmust
* bedefined with:
*INIT_BOARD_EXPORT(fn);
* INIT_DEVICE_EXPORT(fn);
*...
*INIT_APP_EXPORT(fn);
*etc.
*/
int main(void)
{
   unsigned int count = 1;
   /* set LED pin mode to output */
   rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
   while (count > 0)
    {
       /* led on */
       rt_pin_write(LED_PIN, PIN_LOW);
       rt_kprintf("led on, count: %d\n", count);
       rt_thread_mdelay(500);
       /* led off */
       rt_pin_write(LED_PIN, PIN_HIGH);
       rt_kprintf("led off\n");
       rt_thread_mdelay(500);
       count++;
    }
   return 0;
}


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
属于自己原创的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客