CubeMX生成的代码结构如下
CubeMX在生成代码的时候可以选择是否要把库复制到工程所在目录,为了减少外部依赖,我选择把库复制到工程中,这样在生成的工程目录中就包含了库相关的文件。
CubeMX的源代码分为了inc,src和drivers。为了让rtthread的编译工具编译这些文件,需要把src和drivers中的文件需要加入到scons脚本中,而inc只需要把路径加入到scons脚本中。根据前面了解到的sconscript规则,写出src和drivers的规则,并把相关的路径添加在sconscript中。drivers下面有cmsis的system文件和启动文件。在前面的rtt工程中,scons是把cmsis目录下的这两个文件加入了工程中。而CubeMX会根据工程配置情况,把这个system文件生成在src目录,我选择的工具是mdk,启动文件则生成在MDK-ARM目录中。在sconscript中加入CubeMX生成的system文件和启动文件,对于cmsis目录中的文件就不添加了,但是cmsis的路径需要添加到工程中。不同的源代码添加到不同的group中。这样在后面生成ide工程文件的时候也会将他们放在不同的group中。
# RT-Thread building script for component
Import('rtconfig')
from building import *
cwd = GetCurrentDir()
src = Split('''
Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c
''')
CPPPATH = [cwd + '/Device/ST/STM32F7xx/Include', cwd + '/Include']
CPPDEFINES = [rtconfig.STM32_TYPE]
# add for startup script
if rtconfig.CROSS_TOOL == 'gcc':
src += ['Device/ST/STM32F7xx/Source/Templates/gcc/startup_stm32f746xx.s']
elif rtconfig.CROSS_TOOL == 'keil':
src += ['Device/ST/STM32F7xx/Source/Templates/arm/startup_stm32f746xx.s']
elif rtconfig.CROSS_TOOL == 'iar':
src += ['Device/ST/STM32F7xx/Source/Templates/iar/startup_stm32f746xx.s']
group = DefineGroup('CMSIS', [], depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
Return('group')
上面是drivers/cmsis目录的scons规则,这里只添加了头文件路径信息,没有添加源代码,源代码会在MDK-ARM目录的规则中添加。
import rtconfig
Import('RTT_ROOT')
from building import *
# get current directory
cwd = GetCurrentDir()
# The set of source files associated with this SConscript file.
srcx = Glob('Src/*.c')
src = []
for t in srcx:
if t.name.find('template') == -1:
src.append(t)
path = [cwd + '/Inc']
#CPPDEFINES = ['USE_HAL_DRIVER', rtconfig.STM32_TYPE]
CPPDEFINES = ['USE_HAL_DRIVER']
group = DefineGroup('STM32F7xx_HAL_Driver', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
Return('group')
上面是drivers/stm32f7xx_hal_driver目录下的scons规则。添加了c文件和头文件路径,hal库中有一些外设有template文件,这里把template文件去掉了。这里还可以根据stm32 config文件中的宏定义来确定哪些文件需要添加到编译环境中,减少工程中的文件数目。
CubeMX的初始化工作是在main中完成的,而rtt的初始化工作是在hw_init中做的,main只是一个普通的线程。简单点的做法就是把main里面的初始化代码复制到board中去,或者是在main文件中实现init函数。
添加CubeMX版的串口设备,CubeMX的串口初始化由自动生成的代码完成,之前的发送和接收都用的是中断方式。CubeMX的中断方式接收比较奇葩,需要接收指定长度的数据才算完成。而rtthread的中断接收方式是当到来一个字节后,把它放入serial模块管理的buffer中。如果一定要用CubeMX的代码来接收,那就得每次都接收一个字节,这个代价太大,我这里选择接管HAL库的UART中断处理代码,用rtt的方式来接收和发送。UART基本的配置还是沿用CubeMX生成的代码。至此一个基本的rtt程序就算完成了,通过串口可以操作finsh,进行一些基本的命令操作。
void USART3_IRQHandler(void)
{
struct stm32_uart *uart;
uart = &uart1;
/* enter interrupt */
rt_interrupt_enter();
/* UART in mode Receiver ---------------------------------------------------*/
if ((__HAL_UART_GET_IT(&uart->UartHandle, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&uart->UartHandle, UART_IT_RXNE) != RESET))
{
rt_hw_serial_isr(&serial1, RT_SERIAL_EVENT_RX_IND);
/* Clear RXNE interrupt flag */
__HAL_UART_SEND_REQ(&uart->UartHandle, UART_RXDATA_FLUSH_REQUEST);
}
/* leave interrupt */
rt_interrupt_leave();
}
static int stm32_putc(struct rt_serial_device *serial, char c)
{
struct stm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = (struct stm32_uart *)serial->parent.user_data;
while (!(uart->UartHandle.Instance->ISR & UART_FLAG_TXE));
uart->UartHandle.Instance->TDR = c;
return 1;
}
static int stm32_getc(struct rt_serial_device *serial)
{
int ch;
struct stm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = (struct stm32_uart *)serial->parent.user_data;
ch = -1;
if (uart->UartHandle.Instance->ISR & UART_FLAG_RXNE)
{
ch = uart->UartHandle.Instance->RDR & 0xff;
}
return ch;
}
上面的代码用rtthread的串口中断处理机制接管了hal库的中断处理机制,采用中断方式进行串口接收。发送采用的是阻塞方式。
有了串口之后finsh功能就可以用起来了,方便后续的开发调试工作。在这个框架的基础之上,可以添加更多硬件功能和rtt组件。
CubeMXC语言STM32
RTThread与CubeMX – (4)整合RTThread与CubeMX
2017-10-09
CubeMX, rtthread
RTThread与CubeMX – (4)整合RTThread与CubeMX已关闭评论
xtoolbox
CubeMX生成的代码结构如下
CubeMX在生成代码的时候可以选择是否要把库复制到工程所在目录,为了减少外部依赖,我选择把库复制到工程中,这样在生成的工程目录中就包含了库相关的文件。
CubeMX的源代码分为了inc,src和drivers。为了让rtthread的编译工具编译这些文件,需要把src和drivers中的文件需要加入到scons脚本中,而inc只需要把路径加入到scons脚本中。根据前面了解到的sconscript规则,写出src和drivers的规则,并把相关的路径添加在sconscript中。drivers下面有cmsis的system文件和启动文件。在前面的rtt工程中,scons是把cmsis目录下的这两个文件加入了工程中。而CubeMX会根据工程配置情况,把这个system文件生成在src目录,我选择的工具是mdk,启动文件则生成在MDK-ARM目录中。在sconscript中加入CubeMX生成的system文件和启动文件,对于cmsis目录中的文件就不添加了,但是cmsis的路径需要添加到工程中。不同的源代码添加到不同的group中。这样在后面生成ide工程文件的时候也会将他们放在不同的group中。
上面是drivers/cmsis目录的scons规则,这里只添加了头文件路径信息,没有添加源代码,源代码会在MDK-ARM目录的规则中添加。
上面是drivers/stm32f7xx_hal_driver目录下的scons规则。添加了c文件和头文件路径,hal库中有一些外设有template文件,这里把template文件去掉了。这里还可以根据stm32 config文件中的宏定义来确定哪些文件需要添加到编译环境中,减少工程中的文件数目。
CubeMX的初始化工作是在main中完成的,而rtt的初始化工作是在hw_init中做的,main只是一个普通的线程。简单点的做法就是把main里面的初始化代码复制到board中去,或者是在main文件中实现init函数。
添加CubeMX版的串口设备,CubeMX的串口初始化由自动生成的代码完成,之前的发送和接收都用的是中断方式。CubeMX的中断方式接收比较奇葩,需要接收指定长度的数据才算完成。而rtthread的中断接收方式是当到来一个字节后,把它放入serial模块管理的buffer中。如果一定要用CubeMX的代码来接收,那就得每次都接收一个字节,这个代价太大,我这里选择接管HAL库的UART中断处理代码,用rtt的方式来接收和发送。UART基本的配置还是沿用CubeMX生成的代码。至此一个基本的rtt程序就算完成了,通过串口可以操作finsh,进行一些基本的命令操作。
上面的代码用rtthread的串口中断处理机制接管了hal库的中断处理机制,采用中断方式进行串口接收。发送采用的是阻塞方式。
有了串口之后finsh功能就可以用起来了,方便后续的开发调试工作。在这个框架的基础之上,可以添加更多硬件功能和rtt组件。
CubeMXC语言STM32