本文主要是介绍创龙瑞芯微RK3568设备树1(修改设备树GPIO和串口),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
最近一直在搞3568的东西,涉及到底层的设备树修改,驱动编写等等,忙的焦头烂额的,也没时间往下面写东西了。今天差不多底层的东西快弄完了,把最近的感悟给大家分享下,并且加入点设备树的基础知识。给刚刚涉足开发板学习的小伙伴一点帮助。当然对于大神们来说,写的肯定是皮毛。一起共勉!
基础
涉及到的知识,我会用类比的方法和STM32的硬件做对比,其实弄完之后发现两个差不多,没有什么本质的区别。所以小伙伴看之前的基础是必须编写过单片机的程序,对单片机的架构有一定的了解,要不看完会更迷茫。
题外话
学习这个真是很痛苦,并且不知道自己做的对不对,需要一遍一遍的测试。并且问了其他小伙伴,有一个共同的感觉:随着年龄的增加,学习能力大大下降。并且已经抽不出那么多精力去学习能力了。
每天刷抖音,看到什么35岁失业什么的,其实吧,感觉有三个原因吧,仅仅是自己猜测:
(1)技术没有做扎实就转到管理岗了。公司发展太快,所以刚进去的技术还没有很好的基础,就转到管理,使得自己的技术不扎实,再从管理岗转回来,已经很难了。
(2)技术也不错,但是忘记了学习,一直做自己习惯的东西,然后到了管理。但是到了管理之后,技术更新了,以前的技术已经适应不了现在的东西了。这个应该是大部分人的问题吧。就算在一个技术上做的时间长了,也会不学习了,感觉现在的东西够了。当然学习新的东西会很难、很闹心。其实我也想一直做单片机,也就控制几个灯,控制几个外设。然后搞搞逻辑啥的。一直在自己的舒适区。
(3)技术也够,学习也一直在学,但是换个工作工资低了,不愿将就。但愿每个人都是因为这个原因。
内容
这次介绍4个内容,都是最简单的外设:(1)GPIO,(2)串口,(3)I2C,(4)CAN。这4个应该能包含大部分硬件应用了,当然还有麻烦的,后面再慢慢介绍,一点一点的来。先介绍最基本的,大概有个印象。
1.GPIO
GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_Initure.Pin = GPIO_PIN_15; GPIO_Initure.Mode = GPIO_MODE_INPUT; GPIO_Initure.Pull = GPIO_PULLUP; GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOE, &GPIO_Initure);
这个是单片机的GPIO初始化。定义GPIO结构体,开时钟,管脚号,管脚输入,管脚模式,管脚速度,参数传入结构体。
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_SET);
这个是控制程序。直接根据HALk库给的函数就行。要是不用HAL库,自己控制,也都是别人给好的API函数。
对比下来,在Linux的3568设备树里:
gpioled1 {compatible = "MY,led1";led1-gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;status = "okay";};
先说第二句:gpio的管脚定义,第三句:状态定义。
第一句是匹配定义,这个后面再说。后面牵涉到驱动部分,这个后面会详细介绍,所以现在先由个概念,知道是这么回事。
至此到这里,GPIO的设备树部分介绍完毕。下面说下两者的区别,仅仅说对于GPIO设定部分的区别哈,其他的就不说了,没啥用。
相同点:定义了管脚,并且定义了初始电平;
不同点:单片机定义了管脚的输入和输出,3568定义了匹配字。至于语法的区别,就不做过多的介绍了。
所以,3568里面还需要对其他的进行定义,第一个:输入输出定义,第二个:控制程序。这个后面再说。先说下,输入输出定义在驱动里面定义,控制程序也是线程的API,只要拿过来使用就行了。
2.串口
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF7_USART2;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
先说第一部分,管脚定义。这部分应该很熟悉,定义管脚,定义管脚复用,然后定义复用到什么上面,然后参数传入结构体。这部分是管脚的定义。
huart2.Instance = USART2;huart2.Init.BaudRate = 1000000;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;HAL_UART_Init(&huart2);
然后说第二部分,串口定义。前面定义了管脚,相当于管脚已经复用到了串口上,然后定义串口的信息。对应串口2,波特率,起始位,停止位等。
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);HAL_NVIC_EnableIRQ(USART2_IRQn);
然后就是中断函数,接收和发送中断。对应的就是接收和发送函数中断。这个API在it.c里面应该可以找到。要是找不到就直接去库函数里面找。
对比下来,在3568的设备树里:
uart1 {/omit-if-no-ref/uart1m0_xfer: uart1m0-xfer {rockchip,pins =/* uart1_rxm0 */<2 RK_PB3 2 &pcfg_pull_up>,/* uart1_txm0 */<2 RK_PB4 2 &pcfg_pull_up>;};/omit-if-no-ref/uart1m0_ctsn: uart1m0-ctsn {rockchip,pins =/* uart1m0_ctsn */<2 RK_PB6 2 &pcfg_pull_none>;};/omit-if-no-ref/uart1m0_rtsn: uart1m0-rtsn {rockchip,pins =/* uart1m0_rtsn */<2 RK_PB5 2 &pcfg_pull_none>;};/omit-if-no-ref/uart1m1_xfer: uart1m1-xfer {rockchip,pins =/* uart1_rxm1 */<3 RK_PD7 4 &pcfg_pull_up>,/* uart1_txm1 */<3 RK_PD6 4 &pcfg_pull_up>;};/omit-if-no-ref/uart1m1_ctsn: uart1m1-ctsn {rockchip,pins =/* uart1m1_ctsn */<4 RK_PC1 4 &pcfg_pull_none>;};/omit-if-no-ref/uart1m1_rtsn: uart1m1-rtsn {rockchip,pins =/* uart1m1_rtsn */<4 RK_PB6 4 &pcfg_pull_none>;};};
这个是pinctrl里面的设备树结构。里面包含串口的各种复用管脚定义。里面m0和m1可以自己选择,当然选择方法在后面。
对比不同点:单片机里面直接写出来用哪个管脚,用哪个需要自己去写。而3568里面全部给你写出来,然后你自己再配置。
uart1: serial@fe650000 {compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart";reg = <0x0 0xfe650000 0x0 0x100>;interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;clock-names = "baudclk", "apb_pclk";reg-shift = <2>;reg-io-width = <4>;dmas = <&dmac0 2>, <&dmac0 3>;pinctrl-names = "default";pinctrl-0 = <&uart1m0_xfer>;status = "disabled";};
然后底层的设备树,这部分不用修改,别人给写好的。至于怎么写,不用管,只知道在这里就行。
解释下:匹配字,状态,寄存器地址。中断地址,时钟,时钟名称,寄存器偏移,寄存器宽度,DMA,管脚名称,管脚初始定义。
其实在单片机里,中断函数已经给你配好了,而设备树里直接给你写出来了。怎么写的 ,千万别去研究,别人做好的,直接用就行,或者直接知道是啥东西就行。然后管脚选用的是m0。这个是别人的初始定义,后面可以再修改。所以这个地方就看看,知道是啥就行,至于reg啥的,千万别管。
&uart1 {status = "okay";pinctrl-0 = <&uart1m1_xfer>;
};
这是后面的自己定义。前面别人给个初始的,后面用不用看自己。用的话就来个okay,不用就不用管。要是用的话,管脚不一样咋弄,那就给改改。
然后,然后就没了。就那么多东西。
对于GPIO中的驱动,GPIO的驱动简单,可以自己写一个。但是串口的比较麻烦,别人都写好了,不用管。配好设备树之后,linux会自己加载驱动函数。就像单片机里面的收发中断,然后放到buffer里面。其实你也不知道咋驱动的,就是可以收到数,然后解析就行。
切记:千万别深究,千万别深究。
不同
设备树放的比较乱,如果别人开发的不好,放的会更乱,所以选开发板的时候选大厂的。放的位置好,你就好看点,学习起来也快。至于程序放的位置,放哪都行,随你意,但是最好按照别人写好的去放,看起来方便。
单片机里面的东西,都是一块一块的,相对来说,别人都给你封好了,3568或者其他开发板里面的程序都是按照功能一大块放一起,看起来比较麻烦。
总结
设备树就是将单片机的不同的功能,大家放一起,然后自己挑出来。并且用很晦涩的表达方式表达出来,不用看懂具体是啥,也不用纠结怎么去编写,会改管脚就行。给的pdf里面肯定会有说明怎么弄,要是没有,引用别人的话:赶紧跑路,还搞啥,自己肯定编不了。
后续
接触的时候脑袋疼,这是啥,这又是啥。当真的去一个一个的琢磨之后,才发现,哦,和单片机差不多。学习顺序:克服心理障碍,静下心,一句一句的看,不会的查,改,改,改,不用担心改错,反正也改不坏。还有一定要做好备份,在修改任何东西前,一定先保存一份,万一改错了还能复原,再从开始改。
后面介绍I2C和CAN的设备树,然后再介绍GPIO的驱动函数,然后就再ETH,然后再其他的。慢慢来。喜欢的小伙伴点个关注,后续文章继续发送。
这篇关于创龙瑞芯微RK3568设备树1(修改设备树GPIO和串口)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!