开始

  • 概览
  • Gpio对象
    • `config`函数
    • `subscribe`函数
    • `unsubscribe`函数
    • 杂项函数
      • main.cpp中的gpio相关

概览

odrive对stm32的gpio和gpio中断进行了自己的封装,故对其进行分析

Gpio对象

class Stm32Gpio {public:static const Stm32Gpio none;Stm32Gpio() : port_(nullptr), pin_mask_(0) {}Stm32Gpio(GPIO_TypeDef* port, uint16_t pin) : port_(port), pin_mask_(pin) {}operator bool() const { return port_ && pin_mask_; }/*** @brief Configures the GPIO with the specified parameters.* * This can be done regardless of the current state of the GPIO.* * If any subscription is in place, it is not disabled by this function.*/bool config(uint32_t mode, uint32_t pull, uint32_t speed = GPIO_SPEED_FREQ_LOW);void write(bool state) {if (port_) {HAL_GPIO_WritePin(port_, pin_mask_, state ? GPIO_PIN_SET : GPIO_PIN_RESET);}}bool read() {return port_ && (port_->IDR & pin_mask_);}/*** @brief Subscribes to external interrupts on the specified GPIO.* * Before calling this function the gpio should most likely be configured as* input (however this is not mandatory, the interrupt works in output mode* too).* Also you need to enable the EXTIx_IRQn interrupt vectors in the NVIC,* otherwise the subscription won't have any effect.* * Only one subscription is allowed per pin number. I.e. it is not possible* to set up a subscription for both PA0 and PB0 at the same time.* * This function is thread-safe with respect to all other public functions* of this class.* * Returns true if the subscription was set up successfully or false otherwise.*/bool subscribe(bool rising_edge, bool falling_edge, void (*callback)(void*), void* ctx);/*** @brief Unsubscribes from external interrupt on the specified GPIO.* * If no subscription was active for this GPIO, calling this function has no* effect.** This function is thread-safe with respect to all other public functions* of this class, however it must not be called from an interrupt routine* running at a higher priority than the interrupt that is being unsubscribed.** After this function returns the callback given to subscribe() will no* longer be invoked.*/void unsubscribe();uint16_t get_pin_number() {uint16_t pin_number = 0;uint16_t pin_mask = pin_mask_ >> 1;while (pin_mask) {pin_mask >>= 1;pin_number++;}return pin_number;}GPIO_TypeDef* port_;uint16_t pin_mask_; // TODO: store pin_number_ instead of pin_mask_
};

pin_mask_ 用于将gpio的序号改写成便于位操作的形式
eg : pin3 ,pin_mask_ = 0000000000001000
pin0 ,pin_mask_ = 0000000000000001
于是get_pin_number()即为逆向操作

bool read() {return port_ && (port_->IDR & pin_mask_);}

read函数使用直接读取寄存器的方法
write是直接调用HAL库

config函数

bool Stm32Gpio::config(uint32_t mode, uint32_t pull, uint32_t speed) {if (port_ == GPIOA) {__HAL_RCC_GPIOA_CLK_ENABLE();} else if (port_ == GPIOB) {__HAL_RCC_GPIOB_CLK_ENABLE();} else if (port_ == GPIOC) {__HAL_RCC_GPIOC_CLK_ENABLE();} else if (port_ == GPIOD) {__HAL_RCC_GPIOD_CLK_ENABLE();} else if (port_ == GPIOE) {__HAL_RCC_GPIOE_CLK_ENABLE();} else if (port_ == GPIOF) {__HAL_RCC_GPIOF_CLK_ENABLE();} else if (port_ == GPIOG) {__HAL_RCC_GPIOG_CLK_ENABLE();} else if (port_ == GPIOH) {__HAL_RCC_GPIOH_CLK_ENABLE();} else {return false;}size_t position = get_pin_number();// The following code is mostly taken from HAL_GPIO_Init/* Configure IO Direction mode (Input, Output, Alternate or Analog) */uint32_t temp = port_->MODER;temp &= ~(GPIO_MODER_MODER0 << (position * 2U));temp |= ((mode & GPIO_MODE) << (position * 2U));port_->MODER = temp;/* In case of Output or Alternate function mode selection */if((mode == GPIO_MODE_OUTPUT_PP) || (mode == GPIO_MODE_AF_PP) ||(mode == GPIO_MODE_OUTPUT_OD) || (mode == GPIO_MODE_AF_OD)){/* Check the Speed parameter */assert_param(IS_GPIO_SPEED(speed));/* Configure the IO Speed */temp = port_->OSPEEDR; temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2U));temp |= (speed << (position * 2U));port_->OSPEEDR = temp;/* Configure the IO Output Type */temp = port_->OTYPER;temp &= ~(GPIO_OTYPER_OT_0 << position) ;temp |= (((mode & GPIO_OUTPUT_TYPE) >> 4U) << position);port_->OTYPER = temp;}/* Activate the Pull-up or Pull down resistor for the current IO */temp = port_->PUPDR;temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2U));temp |= ((pull) << (position * 2U));port_->PUPDR = temp;return true;
}
  1. 打开时钟
  2. 获取pin_number
  3. 后面进行gpio的初始化(官方注释:基本从HAL库复制)

subscribe函数

bool Stm32Gpio::subscribe(bool rising_edge, bool falling_edge, void (*callback)(void*), void* ctx) {uint32_t pin_number = get_pin_number();if (pin_number >= N_EXTI) {return false; // invalid pin number}struct subscription_t& subscription = subscriptions[pin_number];GPIO_TypeDef* no_port = nullptr;if (!__atomic_compare_exchange_n(&subscription.port, &no_port, port_, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {return false; // already in use}// The following code is mostly taken from HAL_GPIO_Init__HAL_RCC_SYSCFG_CLK_ENABLE();uint32_t temp = SYSCFG->EXTICR[pin_number >> 2U];temp &= ~(0x0FU << (4U * (pin_number & 0x03U)));temp |= ((uint32_t)(GPIO_GET_INDEX(port_)) << (4U * (pin_number & 0x03U)));SYSCFG->EXTICR[pin_number >> 2U] = temp;if (rising_edge) {EXTI->RTSR |= (uint32_t)pin_mask_;} else {EXTI->RTSR &= ~((uint32_t)pin_mask_);}if (falling_edge) {EXTI->FTSR |= (uint32_t)pin_mask_;} else {EXTI->FTSR &= ~((uint32_t)pin_mask_);}EXTI->EMR &= ~((uint32_t)pin_mask_);EXTI->IMR |= (uint32_t)pin_mask_;// Clear any previous triggers__HAL_GPIO_EXTI_CLEAR_IT(pin_mask_);subscription.ctx = ctx;subscription.callback = callback;return true;
}

该函数是配置相关gpio的中断的它没有进行gpio input或output的配置,也没有开中断
同时还有一个结构体数组保存相应的中断线信息


#define N_EXTI 16struct subscription_t {GPIO_TypeDef* port = nullptr;void (*callback)(void*) = nullptr;void* ctx = nullptr;
} subscriptions[N_EXTI];

未知ctx是干啥的,上下文?求教 ctx作为输入参数传入calllback

unsubscribe函数

即取消gpio的中断线和deinit subscriptions中的配置

杂项函数

void maybe_handle(uint16_t exti_number) {if(__HAL_GPIO_EXTI_GET_IT(1 << exti_number) == RESET) {return; // This interrupt source did not trigger the interrupt line}__HAL_GPIO_EXTI_CLEAR_IT(1 << exti_number);if (exti_number >= N_EXTI) {return;}subscription_t& subscription = subscriptions[exti_number];if (subscription.callback) {(*subscription.callback)(subscription.ctx);}
}

这是gpio的中断线处理程序,首先判断是不是这个gpio的中断请求,然后清标志位,防溢出,调用callback,ctx作为参数传入

main.cpp中的gpio相关

main.hpp中还有个函数

static Stm32Gpio get_gpio(size_t gpio_num) {return (gpio_num < GPIO_COUNT) ? gpios[gpio_num] : GPIO_COUNT ? gpios[0] : Stm32Gpio::none;
}

它将gpio_num转换成Stm32Gpio 而有个Stm32Gpio gpios[]保存着每个gpio的参数,它被存在board.c文件中
本文完,To be countinue…

Odrive_0.5.5运行代码分析_(三)_GPIO详解相关推荐

  1. 代码分析 | 单细胞转录组clustering详解

    聚类可视化 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 (重磅综述: ...

  2. 代码分析 | 单细胞转录组Normalization详解

    标准化加高变基因选择 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 ( ...

  3. 代码分析 | 单细胞转录组质控详解

    前言 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 (重磅综述:三万字 ...

  4. ★核心关注点_《信息系统项目管理师考试考点分析与真题详解》

    ★核心关注点_<信息系统项目管理师考试考点分析与真题详解> 真诚感谢你选用<信息系统项目管理师考试考点分析与真题详解>作为高级项管的辅导用书.对于使用该书的读者们,在备考201 ...

  5. 好程序员技术分析JavaScript闭包特性详解

    为什么80%的码农都做不了架构师?>>>    好程序员技术分析JavaScript闭包特性详解,今天来总结一下js闭包的那些事,以及遇到的坑和解决方法,希望对你有所帮助. 是的,没 ...

  6. Android 事件分发机制分析及源码详解

    Android 事件分发机制分析及源码详解 文章目录 Android 事件分发机制分析及源码详解 事件的定义 事件分发序列模型 分发序列 分发模型 事件分发对象及相关方法 源码分析 事件分发总结 一般 ...

  7. php输出源代码,PHP源代码分析-echo实现详解

    PHP源代码分析-echo实现详解 echo,这个是PHP运用得最多的标记之一,算不上是函数,PHP手册里这么写的,因为它没有返回值.今天好奇就去看看PHP的源代码,因为echo不是一般的函数,所以找 ...

  8. 【 卷积神经网络CNN 数学原理分析与源码详解 深度学习 Pytorch笔记 B站刘二大人(9/10)】

    卷积神经网络CNN 数学原理分析与源码详解 深度学习 Pytorch笔记 B站刘二大人(9/10) 本章主要进行卷积神经网络的相关数学原理和pytorch的对应模块进行推导分析 代码也是通过demo实 ...

  9. 一篇文章带你快速理解JVM运行时数据区 、程序计数器详解 (手画详图)值得收藏!!!

    受多种情况的影响,又开始看JVM 方面的知识. 1.Java 实在过于内卷,没法不往深了学. 2.面试题问的多,被迫学习. 3.纯粹的好奇. 很喜欢一句话:"八小时内谋生活,八小时外谋发展. ...

最新文章

  1. sentinel限流_微服务架构进阶:Sentinel实现服务限流、熔断与降级
  2. python制作验证码_Python编写生成验证码的脚本的教程
  3. Oralce分析函数
  4. with as 用法 oracle,with.as oracle的用法
  5. bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)
  6. python po设计模式_Python Selenium设计模式 - PO设计模式
  7. python可以干嘛-python都可以用来做什么
  8. oracle数据库赋权_(转)Oracle数据库如何授权收费(Database Licensing)
  9. 如何在Java中执行Python模块?从认识JEP库开始
  10. (附源码)springboot电子阅览室app 毕业设计 016514
  11. 提供一个vs2010 sp1的下载
  12. java缓存机制面试题,电子版已问世
  13. 辞职文案火了,程序员的辞职理由要命不要钱。
  14. 演示固态硬盘装win11系统教程
  15. 一步一步教你在Linux上搭建云服务器
  16. 无线网460王者荣耀服务器,王者荣耀:如何解决大批玩家网络460?骨灰级玩家给出了最终方案...
  17. vs2008编译QT开源项目--太阳神三国杀源码分析(一) 项目编译及整体分析
  18. 腾讯云iis8.5新建网站无法访问_如何建立自己的网站(零基础小白教程一)
  19. 海峰五笔试用体验,感觉上当受骗……
  20. Conflux 研究院 | 《Conflux 协议规范》(黄皮书)导读

热门文章

  1. 硬盘无法格式化及RAW格式的另一种处理方法
  2. 硬盘突然变raw格式_磁盘变成RAW格式的完美解决方式
  3. 腾讯云服务器无法通过密钥登录
  4. GGDH模型计算浮升力生成项
  5. vs2013 调用webapi出错,请求的资源不支持 http 方法“GET”
  6. LinuxShell宝典
  7. 联想开机按f2怎么修复系统图解_windows10开机按f几进入一键还原 按下F2就进入联想电脑拯救系...
  8. 双壳层膦酰基修饰二氧化硅磁性微球/氮氧自由基接枝/表面KH-550改性二氧化硅微球的研究
  9. 一开机checkingmedia_开机出现checkingmedia提示解决方法
  10. 英语测试软件怎么没反应呢,有没有可以练习中考英语口语的软件【2017年最新版】...