Odrive_0.5.5运行代码分析_(三)_GPIO详解
开始
- 概览
- 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;
}
- 打开时钟
- 获取pin_number
- 后面进行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详解相关推荐
- 代码分析 | 单细胞转录组clustering详解
聚类可视化 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 (重磅综述: ...
- 代码分析 | 单细胞转录组Normalization详解
标准化加高变基因选择 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 ( ...
- 代码分析 | 单细胞转录组质控详解
前言 NGS系列文章包括NGS基础.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞测序分析 (重磅综述:三万字 ...
- ★核心关注点_《信息系统项目管理师考试考点分析与真题详解》
★核心关注点_<信息系统项目管理师考试考点分析与真题详解> 真诚感谢你选用<信息系统项目管理师考试考点分析与真题详解>作为高级项管的辅导用书.对于使用该书的读者们,在备考201 ...
- 好程序员技术分析JavaScript闭包特性详解
为什么80%的码农都做不了架构师?>>> 好程序员技术分析JavaScript闭包特性详解,今天来总结一下js闭包的那些事,以及遇到的坑和解决方法,希望对你有所帮助. 是的,没 ...
- Android 事件分发机制分析及源码详解
Android 事件分发机制分析及源码详解 文章目录 Android 事件分发机制分析及源码详解 事件的定义 事件分发序列模型 分发序列 分发模型 事件分发对象及相关方法 源码分析 事件分发总结 一般 ...
- php输出源代码,PHP源代码分析-echo实现详解
PHP源代码分析-echo实现详解 echo,这个是PHP运用得最多的标记之一,算不上是函数,PHP手册里这么写的,因为它没有返回值.今天好奇就去看看PHP的源代码,因为echo不是一般的函数,所以找 ...
- 【 卷积神经网络CNN 数学原理分析与源码详解 深度学习 Pytorch笔记 B站刘二大人(9/10)】
卷积神经网络CNN 数学原理分析与源码详解 深度学习 Pytorch笔记 B站刘二大人(9/10) 本章主要进行卷积神经网络的相关数学原理和pytorch的对应模块进行推导分析 代码也是通过demo实 ...
- 一篇文章带你快速理解JVM运行时数据区 、程序计数器详解 (手画详图)值得收藏!!!
受多种情况的影响,又开始看JVM 方面的知识. 1.Java 实在过于内卷,没法不往深了学. 2.面试题问的多,被迫学习. 3.纯粹的好奇. 很喜欢一句话:"八小时内谋生活,八小时外谋发展. ...
最新文章
- sentinel限流_微服务架构进阶:Sentinel实现服务限流、熔断与降级
- python制作验证码_Python编写生成验证码的脚本的教程
- Oralce分析函数
- with as 用法 oracle,with.as oracle的用法
- bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)
- python po设计模式_Python Selenium设计模式 - PO设计模式
- python可以干嘛-python都可以用来做什么
- oracle数据库赋权_(转)Oracle数据库如何授权收费(Database Licensing)
- 如何在Java中执行Python模块?从认识JEP库开始
- (附源码)springboot电子阅览室app 毕业设计 016514
- 提供一个vs2010 sp1的下载
- java缓存机制面试题,电子版已问世
- 辞职文案火了,程序员的辞职理由要命不要钱。
- 演示固态硬盘装win11系统教程
- 一步一步教你在Linux上搭建云服务器
- 无线网460王者荣耀服务器,王者荣耀:如何解决大批玩家网络460?骨灰级玩家给出了最终方案...
- vs2008编译QT开源项目--太阳神三国杀源码分析(一) 项目编译及整体分析
- 腾讯云iis8.5新建网站无法访问_如何建立自己的网站(零基础小白教程一)
- 海峰五笔试用体验,感觉上当受骗……
- Conflux 研究院 | 《Conflux 协议规范》(黄皮书)导读
热门文章
- 硬盘无法格式化及RAW格式的另一种处理方法
- 硬盘突然变raw格式_磁盘变成RAW格式的完美解决方式
- 腾讯云服务器无法通过密钥登录
- GGDH模型计算浮升力生成项
- vs2013 调用webapi出错,请求的资源不支持 http 方法“GET”
- LinuxShell宝典
- 联想开机按f2怎么修复系统图解_windows10开机按f几进入一键还原 按下F2就进入联想电脑拯救系...
- 双壳层膦酰基修饰二氧化硅磁性微球/氮氧自由基接枝/表面KH-550改性二氧化硅微球的研究
- 一开机checkingmedia_开机出现checkingmedia提示解决方法
- 英语测试软件怎么没反应呢,有没有可以练习中考英语口语的软件【2017年最新版】...