我们可以为方便起见编辑回调函数 HAL_UART_TxCpltCallback 吗?
Can we edit callback function HAL_UART_TxCpltCallback for our convenience?
我是 FreeRTOS 和 STM32 的新手。我想知道 HAL_UART_Transmit_IT 的回调函数 HAL_UART_TxCpltCallback 是如何工作的?
我们可以为方便起见编辑那个回调函数吗?
提前致谢
您调用 HAL_UART_Transmit_IT
以 "interrupt"(非阻塞)模式传输您的数据。此调用会立即调用 returns,很可能在您的数据被完全传输之前。
事件顺序如下:
HAL_UART_Transmit_IT
存储您提供的数据缓冲区的指针和长度。它不执行复制,因此您传递的缓冲区需要在调用回调之前保持有效。例如,它不能是您将在回调发生之前执行 delete []
/ free
的缓冲区,也不能是您将要在回调调用之前 return 执行的函数中的本地缓冲区。
然后为该 UART 启用 TXE
中断,每次 DR
(或 TDR
,取决于使用的 STM)为空且可以写入新数据
此时中断立即发生。在 IRQ 处理程序 (HAL_UART_IRQHandler
) 中,一个新字节被放入 DR
(TDR
) 寄存器,然后被传输 - 这发生在 UART_Transmit_IT
.
传输此字节后,TXE
中断将再次触发并重复此过程,直到到达您提供的缓冲区的末尾。
如果发生任何错误,HAL_UART_ErrorCallback
将被调用,来自 IRQ 处理程序
如果没有错误发生并且已到达缓冲区末尾,则调用 HAL_UART_TxCpltCallback
(从 HAL_UART_IRQHandler
-> UART_EndTransmit_IT
)。
关于你的第二个问题,你是否可以编辑这个回调 "for convenience" - 我会说你可以做任何你想做的事,但你必须忍受修改代码的后果,本质上是一个库:
将 HAL 升级到更新的版本将是一场噩梦。您必须手动重新应用您对该代码所做的所有更改并再次测试它们。在某种程度上,这可以通过某种形式的版本控制(git / svn)甚至补丁文件自动实现,但如果你修改的代码被 ST 更改,这些补丁可能不再适用,你'将不得不再次手工完成这一切。这可能需要重新发现实现的变化并从头开始完成所有工作。
没有人能够帮助您,因为您的库代码不再与其他人拥有的代码匹配。如果您通过修改库代码引入了新的错误,那么没有人能够重现它们。即使您提供了您的修改,老实说,我怀疑这里的许多人是否会费心应用您的更改并在实践中测试它们。
如果我要表达我的个人观点,那就是:如果您认为 HAL 代码中存在错误 - 在本地修复它们并将它们报告给 ST。一旦它们在未来的更新中得到修复,请使用更新的官方版本完全覆盖您的 HAL 修改。如果您认为 HAL 代码缺乏满足您需求的功能或灵活性,您有两个选择:
建议您对 ST 进行更改。您必须记住,HAL 旨在满足 "general purpose" 需求。
只是不要将 HAL 用于此特定外围设备。这种 "mixed" 方法正是我个人所做的。在某些情况下,HAL 为给定外设提供的功能 "good enough" 可以满足我的需求(在我的例子中,一个例子是 SPI,我完全依赖 HAL),而在其他一些情况下——比如 UART——我只将 HAL 用于初始化,同时自己处理传输。即使您决定不使用 HAL 函数,它仍然可以提供一些价值——例如,您可以将它们的 IRQ 处理程序复制到您的代码中并调用您的函数。这样你至少可以跳过开发中的一些部分。
我是 FreeRTOS 和 STM32 的新手。我想知道 HAL_UART_Transmit_IT 的回调函数 HAL_UART_TxCpltCallback 是如何工作的? 我们可以为方便起见编辑那个回调函数吗?
提前致谢
您调用 HAL_UART_Transmit_IT
以 "interrupt"(非阻塞)模式传输您的数据。此调用会立即调用 returns,很可能在您的数据被完全传输之前。
事件顺序如下:
HAL_UART_Transmit_IT
存储您提供的数据缓冲区的指针和长度。它不执行复制,因此您传递的缓冲区需要在调用回调之前保持有效。例如,它不能是您将在回调发生之前执行delete []
/free
的缓冲区,也不能是您将要在回调调用之前 return 执行的函数中的本地缓冲区。然后为该 UART 启用
TXE
中断,每次DR
(或TDR
,取决于使用的 STM)为空且可以写入新数据此时中断立即发生。在 IRQ 处理程序 (
HAL_UART_IRQHandler
) 中,一个新字节被放入DR
(TDR
) 寄存器,然后被传输 - 这发生在UART_Transmit_IT
.传输此字节后,
TXE
中断将再次触发并重复此过程,直到到达您提供的缓冲区的末尾。如果发生任何错误,
HAL_UART_ErrorCallback
将被调用,来自 IRQ 处理程序如果没有错误发生并且已到达缓冲区末尾,则调用
HAL_UART_TxCpltCallback
(从HAL_UART_IRQHandler
->UART_EndTransmit_IT
)。
关于你的第二个问题,你是否可以编辑这个回调 "for convenience" - 我会说你可以做任何你想做的事,但你必须忍受修改代码的后果,本质上是一个库:
将 HAL 升级到更新的版本将是一场噩梦。您必须手动重新应用您对该代码所做的所有更改并再次测试它们。在某种程度上,这可以通过某种形式的版本控制(git / svn)甚至补丁文件自动实现,但如果你修改的代码被 ST 更改,这些补丁可能不再适用,你'将不得不再次手工完成这一切。这可能需要重新发现实现的变化并从头开始完成所有工作。
没有人能够帮助您,因为您的库代码不再与其他人拥有的代码匹配。如果您通过修改库代码引入了新的错误,那么没有人能够重现它们。即使您提供了您的修改,老实说,我怀疑这里的许多人是否会费心应用您的更改并在实践中测试它们。
如果我要表达我的个人观点,那就是:如果您认为 HAL 代码中存在错误 - 在本地修复它们并将它们报告给 ST。一旦它们在未来的更新中得到修复,请使用更新的官方版本完全覆盖您的 HAL 修改。如果您认为 HAL 代码缺乏满足您需求的功能或灵活性,您有两个选择:
建议您对 ST 进行更改。您必须记住,HAL 旨在满足 "general purpose" 需求。
只是不要将 HAL 用于此特定外围设备。这种 "mixed" 方法正是我个人所做的。在某些情况下,HAL 为给定外设提供的功能 "good enough" 可以满足我的需求(在我的例子中,一个例子是 SPI,我完全依赖 HAL),而在其他一些情况下——比如 UART——我只将 HAL 用于初始化,同时自己处理传输。即使您决定不使用 HAL 函数,它仍然可以提供一些价值——例如,您可以将它们的 IRQ 处理程序复制到您的代码中并调用您的函数。这样你至少可以跳过开发中的一些部分。