參考:Linux之ARM(IMX6U)裸機模仿STM32驅動開發格式
作者:一只青木呀
發布時間: 2020-08-15 12:11:56
網址:https://blog.csdn.net/weixin_45309916/article/details/108019447
目錄
- 0.外設結構體抽象思路
- 1.模仿STM32寄存器的定義
- 1.1、STM32寄存器定義方式
- 1.2、I.MX6U寄存器定義步驟
- 1.編寫外設結構體
- 2.定義 IO 復用寄存器組的基地址
- 3.定義訪問指針
- 2.硬件原理分析,和之前的硬件資源一樣
- 3.實驗程序編寫
- 1.imx6ul.h
- 2.main.c
- 3.start.s
- 4.編譯下載驗證
- 1.編寫鏈接腳本
- 2.編寫Makefile腳本
- 3.編譯下載
0.外設結構體抽象思路
之前C 語言編寫 LED 燈驅動的時候,每個寄存器的地址我們都需要寫宏定義,使用起來非常的不方便。我們在學習 STM32 的時候,可以使用“GPIOB->ODR”這種方式來給GPIOB 的寄存器 ODR 賦值,因為在 STM32 中同屬于一個外設的所有寄存器地址基本是相鄰的(有些會有保留寄存器)。
因此我們可以借助 C 語言里面的結構體成員地址遞增的特點來將某個外設的所有寄存器寫入到一個結構體里面,然后定義一個結構體指針指向這個外設的寄存器基地址,這樣我們就可以通過這個結構體指針來訪問這個外設的所有寄存器。也就是將結構體抽象為外設。
同理, I.MX6U 也可以使用這種方法來定義外設寄存器,本次我們就模仿 STM32 里面的寄存器定義方式來編寫I.MX6U 的驅動。
1.模仿STM32寄存器的定義
1.1、STM32寄存器定義方式
為了開發方便, ST 官方為 STM32F103 編寫了一個叫做 stm32f10x.h 的文件,在這個文件里面定義了 STM32F103 所有外設寄存器并放在結構體里面,我們可以使用其定義的寄存器來進行開發,比如我們可以用如下代碼來初始化一個 GPIO:
GPIOE
->CRL
&=0XFF0FFFFF;GPIOE
->CRL
|=0X00300000; GPIOE
->ODR
|=1<<5;
上述代碼是初始化 STM32 的 PE5 這個 GPIO 為推挽輸出,需要配置的就是 GPIOE 的寄存器 CRL 和 ODR, “GPIOE”的定義:
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
可以看出“GPIOE”是個宏定義,是一個指向地址 GPIOE_BASE 的結構體指針,結構體為GPIO_TypeDef, GPIO_TypeDef 和 GPIOE_BASE 的定義如下:
typedef struct
{__IO
uint32_t CRL
;__IO
uint32_t CRH
;__IO
uint32_t IDR
;__IO
uint32_t ODR
;__IO
uint32_t BSRR
;__IO
uint32_t BRR
;__IO
uint32_t LCKR
;
} GPIO_TypeDef
;#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define PERIPH_BASE ((uint32_t)0x40000000)
上述定義中 GPIO_TypeDef 是個結構體,結構體里面的成員變量有 CRL、 CRH、 IDR、 ODR、BSRR、 BRR 和 LCKR,這些都是 GPIO 的寄存器,每個成員變量都是 32 位(4 字節),這些寄存器在結構體中的位置都是按照其地址值從小到大排序的。GPIOE_BASE 就是 GPIOE 的基地址,其為:
GPIOE_BASE
=APB2PERIPH_BASE
+0x1800= PERIPH_BASE
+ 0x10000 + 0x1800=0x40000000 + 0x10000 + 0x1800=0x40011800
GPIOE_BASE 的基地址為 0x40011800,宏 GPIOE 指向這個地址,因此 GPIOE 的寄存器CRL 的地址就是 0X40011800,寄存器 CRH 的地址就是 0X40011800+4=0X40011804,其他寄存器地址以此類推。我們要操作 GPIOE 的 ODR 寄存器的話就可以通過“GPIOE->ODR”來實現,這個方法是借助了結構體成員地址連續遞增的原理。
了解了 STM32 的寄存器定義以后,我們就可以參考其原理來編寫 I.MX6U 的外設寄存器定義了。 NXP 官方并沒有為 I.MX6UL 編寫類似 stm32f10x.h 這樣的文件, NXP 只為 I.MX6ULL提供了類似 stm32f10x.h 這樣的文件,名為 MCIMX6Y2.h,但是 I.MX6UL 和 I.MX6ULL 幾乎一模一樣,所以文件 MCIMX6Y2.h 可以用在 I.MX6UL 上。
1.2、I.MX6U寄存器定義步驟
參考 STM32 的官方文件來編寫 I.MX6U 的寄存器定義,比如 IO 復用寄存器組“IOMUX_SW_MUX_CTL_PAD_XX”,步驟如下:
1.編寫外設結構體
typedef struct{volatile unsigned int BOOT_MODE0
;volatile unsigned int BOOT_MODE1
;volatile unsigned int SNVS_TAMPER0
;volatile unsigned int SNVS_TAMPER1
;………
volatile unsigned int CSI_DATA00
;volatile unsigned int CSI_DATA01
;volatile unsigned int CSI_DATA02
;volatile unsigned int CSI_DATA03
;volatile unsigned int CSI_DATA04
;volatile unsigned int CSI_DATA05
;volatile unsigned int CSI_DATA06
;volatile unsigned int CSI_DATA07
;
115}IOMUX_SW_MUX_Tpye
;
上述結構體 IOMUX_SW_MUX_Type 就是 IO 復用寄存器組,成員變量是每個 IO 對應的復用寄存器,每個寄存器的地址是 32 位,每個成員都使用“volatile”進行了修飾,目的是防止編譯器優化。
2.定義 IO 復用寄存器組的基地址
根據結構體 IOMUX_SW_MUX_Type 的定義,其第一個成員變量為 BOOT_MODE0,也就是 BOOT_MODE0 這個 IO 的 IO 復用寄存器,查找 I.MX6U 的參考手冊可以得知其地址為0X020E0014,所以 IO 復用寄存器組的基地址就是 0X020E0014,定義如下:
#define IOMUX_SW_MUX_BASE (0X020E0014)
3.定義訪問指針
訪問指針定義如下:
#define IOMUX_SW_MUX ((IOMUX_SW_MUX_Type *)IOMUX_SW_MUX_BASE)
通過上面三步我們就可以通過“IOMUX_SW_MUX->GPIO1_IO03”來訪問 GPIO1_IO03 的IO 復用寄存器了。同樣的,其他的外設寄存器都可以通過這三步來定義
2.硬件原理分析,和之前的硬件資源一樣
3.實驗程序編寫
創建 VSCode 工程,工作區名字為“ledc_stm32”,新建三個文件: start.s、 main.c 和 imx6ul.h。
其中 start.s 是匯編文件, main.c和 imx6ul.h 是 C 文件,
1.imx6ul.h
文件 imx6ul.h 用來存放外設寄存器定義,在 imx6ul.h 中輸入如下代碼:
要去imx6ul參考手冊找到這些寄存器的地址,比如下面的CCM寄存器。
#define CCM_BASE (0X020C4000)
#define CCM_ANALOG_BASE (0X020C8000)
#define IOMUX_SW_MUX_BASE (0X020E0014)
#define IOMUX_SW_PAD_BASE (0X020E0204)
#define GPIO1_BASE (0x0209C000)
#define GPIO2_BASE (0x020A0000)
#define GPIO3_BASE (0x020A4000)
#define GPIO4_BASE (0x020A8000)
#define GPIO5_BASE (0x020AC000)
typedef struct
{volatile unsigned int CCR
;volatile unsigned int CCDR
;volatile unsigned int CSR
;volatile unsigned int CCSR
;volatile unsigned int CACRR
;volatile unsigned int CBCDR
;volatile unsigned int CBCMR
;volatile unsigned int CSCMR1
;volatile unsigned int CSCMR2
;volatile unsigned int CSCDR1
;volatile unsigned int CS1CDR
;volatile unsigned int CS2CDR
;volatile unsigned int CDCDR
;volatile unsigned int CHSCCDR
;volatile unsigned int CSCDR2
;volatile unsigned int CSCDR3
; volatile unsigned int RESERVED_1
[2];volatile unsigned int CDHIPR
; volatile unsigned int RESERVED_2
[2];volatile unsigned int CLPCR
;volatile unsigned int CISR
;volatile unsigned int CIMR
;volatile unsigned int CCOSR
;volatile unsigned int CGPR
;volatile unsigned int CCGR0
;volatile unsigned int CCGR1
;volatile unsigned int CCGR2
;volatile unsigned int CCGR3
;volatile unsigned int CCGR4
;volatile unsigned int CCGR5
;volatile unsigned int CCGR6
;volatile unsigned int RESERVED_3
[1];volatile unsigned int CMEOR
;
} CCM_Type
; typedef struct
{volatile unsigned int PLL_ARM
;volatile unsigned int PLL_ARM_SET
;volatile unsigned int PLL_ARM_CLR
;volatile unsigned int PLL_ARM_TOG
;volatile unsigned int PLL_USB1
;volatile unsigned int PLL_USB1_SET
;volatile unsigned int PLL_USB1_CLR
;volatile unsigned int PLL_USB1_TOG
;volatile unsigned int PLL_USB2
;volatile unsigned int PLL_USB2_SET
;volatile unsigned int PLL_USB2_CLR
;volatile unsigned int PLL_USB2_TOG
;volatile unsigned int PLL_SYS
;volatile unsigned int PLL_SYS_SET
;volatile unsigned int PLL_SYS_CLR
;volatile unsigned int PLL_SYS_TOG
;volatile unsigned int PLL_SYS_SS
;volatile unsigned int RESERVED_1
[3];volatile unsigned int PLL_SYS_NUM
;volatile unsigned int RESERVED_2
[3];volatile unsigned int PLL_SYS_DENOM
; volatile unsigned int RESERVED_3
[3];volatile unsigned int PLL_AUDIO
;volatile unsigned int PLL_AUDIO_SET
;volatile unsigned int PLL_AUDIO_CLR
;volatile unsigned int PLL_AUDIO_TOG
;volatile unsigned int PLL_AUDIO_DENOM
;volatile unsigned int RESERVED_4
[3];volatile unsigned int PLL_VIDEO
;volatile unsigned int PLL_VIDEO_SET
;volatile unsigned int PLL_VIDEO_CLR
;volatile unsigned int PLL_VIDEO_TOG
;volatile unsigned int PLL_VIDEO_NUM
;volatile unsigned int RESERVED_5
[3];volatile unsigned int PLL_VIDEO_DENOM
;volatile unsigned int RESERVED_6
[7];volatile unsigned int PLL_ENET
;volatile unsigned int PLL_ENET_SET
;volatile unsigned int PLL_ENET_CLR
;volatile unsigned int PLL_ENET_TOG
;volatile unsigned int PFD_480
;volatile unsigned int PFD_480_SET
;volatile unsigned int PFD_480_CLR
;volatile unsigned int PFD_480_TOG
;volatile unsigned int PFD_528
;volatile unsigned int PFD_528_SET
;volatile unsigned int PFD_528_CLR
;volatile unsigned int PFD_528_TOG
;volatile unsigned int RESERVED_7
[16];volatile unsigned int MISC0
;volatile unsigned int MISC0_SET
;volatile unsigned int MISC0_CLR
;volatile unsigned int MISC0_TOG
;volatile unsigned int MISC1
;volatile unsigned int MISC1_SET
;volatile unsigned int MISC1_CLR
;volatile unsigned int MISC1_TOG
;volatile unsigned int MISC2
;volatile unsigned int MISC2_SET
;volatile unsigned int MISC2_CLR
;volatile unsigned int MISC2_TOG
;
} CCM_ANALOG_Type
;
typedef struct
{volatile unsigned int BOOT_MODE0
;volatile unsigned int BOOT_MODE1
;volatile unsigned int SNVS_TAMPER0
;volatile unsigned int SNVS_TAMPER1
;volatile unsigned int SNVS_TAMPER2
;volatile unsigned int SNVS_TAMPER3
;volatile unsigned int SNVS_TAMPER4
;volatile unsigned int SNVS_TAMPER5
;volatile unsigned int SNVS_TAMPER6
;volatile unsigned int SNVS_TAMPER7
;volatile unsigned int SNVS_TAMPER8
;volatile unsigned int SNVS_TAMPER9
;volatile unsigned int JTAG_MOD
;volatile unsigned int JTAG_TMS
;volatile unsigned int JTAG_TDO
;volatile unsigned int JTAG_TDI
;volatile unsigned int JTAG_TCK
;volatile unsigned int JTAG_TRST_B
;volatile unsigned int GPIO1_IO00
;volatile unsigned int GPIO1_IO01
;volatile unsigned int GPIO1_IO02
;volatile unsigned int GPIO1_IO03
;volatile unsigned int GPIO1_IO04
;volatile unsigned int GPIO1_IO05
;volatile unsigned int GPIO1_IO06
;volatile unsigned int GPIO1_IO07
;volatile unsigned int GPIO1_IO08
;volatile unsigned int GPIO1_IO09
;volatile unsigned int UART1_TX_DATA
;volatile unsigned int UART1_RX_DATA
;volatile unsigned int UART1_CTS_B
;volatile unsigned int UART1_RTS_B
;volatile unsigned int UART2_TX_DATA
;volatile unsigned int UART2_RX_DATA
;volatile unsigned int UART2_CTS_B
;volatile unsigned int UART2_RTS_B
;volatile unsigned int UART3_TX_DATA
;volatile unsigned int UART3_RX_DATA
;volatile unsigned int UART3_CTS_B
;volatile unsigned int UART3_RTS_B
;volatile unsigned int UART4_TX_DATA
;volatile unsigned int UART4_RX_DATA
;volatile unsigned int UART5_TX_DATA
;volatile unsigned int UART5_RX_DATA
;volatile unsigned int ENET1_RX_DATA0
;volatile unsigned int ENET1_RX_DATA1
;volatile unsigned int ENET1_RX_EN
;volatile unsigned int ENET1_TX_DATA0
;volatile unsigned int ENET1_TX_DATA1
;volatile unsigned int ENET1_TX_EN
;volatile unsigned int ENET1_TX_CLK
;volatile unsigned int ENET1_RX_ER
;volatile unsigned int ENET2_RX_DATA0
;volatile unsigned int ENET2_RX_DATA1
;volatile unsigned int ENET2_RX_EN
;volatile unsigned int ENET2_TX_DATA0
;volatile unsigned int ENET2_TX_DATA1
;volatile unsigned int ENET2_TX_EN
;volatile unsigned int ENET2_TX_CLK
;volatile unsigned int ENET2_RX_ER
;volatile unsigned int LCD_CLK
;volatile unsigned int LCD_ENABLE
;volatile unsigned int LCD_HSYNC
;volatile unsigned int LCD_VSYNC
;volatile unsigned int LCD_RESET
;volatile unsigned int LCD_DATA00
;volatile unsigned int LCD_DATA01
;volatile unsigned int LCD_DATA02
;volatile unsigned int LCD_DATA03
;volatile unsigned int LCD_DATA04
;volatile unsigned int LCD_DATA05
;volatile unsigned int LCD_DATA06
;volatile unsigned int LCD_DATA07
;volatile unsigned int LCD_DATA08
;volatile unsigned int LCD_DATA09
;volatile unsigned int LCD_DATA10
;volatile unsigned int LCD_DATA11
;volatile unsigned int LCD_DATA12
;volatile unsigned int LCD_DATA13
;volatile unsigned int LCD_DATA14
;volatile unsigned int LCD_DATA15
;volatile unsigned int LCD_DATA16
;volatile unsigned int LCD_DATA17
;volatile unsigned int LCD_DATA18
;volatile unsigned int LCD_DATA19
;volatile unsigned int LCD_DATA20
;volatile unsigned int LCD_DATA21
;volatile unsigned int LCD_DATA22
;volatile unsigned int LCD_DATA23
;volatile unsigned int NAND_RE_B
;volatile unsigned int NAND_WE_B
;volatile unsigned int NAND_DATA00
;volatile unsigned int NAND_DATA01
;volatile unsigned int NAND_DATA02
;volatile unsigned int NAND_DATA03
;volatile unsigned int NAND_DATA04
;volatile unsigned int NAND_DATA05
;volatile unsigned int NAND_DATA06
;volatile unsigned int NAND_DATA07
;volatile unsigned int NAND_ALE
;volatile unsigned int NAND_WP_B
;volatile unsigned int NAND_READY_B
;volatile unsigned int NAND_CE0_B
;volatile unsigned int NAND_CE1_B
;volatile unsigned int NAND_CLE
;volatile unsigned int NAND_DQS
;volatile unsigned int SD1_CMD
;volatile unsigned int SD1_CLK
;volatile unsigned int SD1_DATA0
;volatile unsigned int SD1_DATA1
;volatile unsigned int SD1_DATA2
;volatile unsigned int SD1_DATA3
;volatile unsigned int CSI_MCLK
;volatile unsigned int CSI_PIXCLK
;volatile unsigned int CSI_VSYNC
;volatile unsigned int CSI_HSYNC
;volatile unsigned int CSI_DATA00
;volatile unsigned int CSI_DATA01
;volatile unsigned int CSI_DATA02
;volatile unsigned int CSI_DATA03
;volatile unsigned int CSI_DATA04
;volatile unsigned int CSI_DATA05
;volatile unsigned int CSI_DATA06
;volatile unsigned int CSI_DATA07
;
}IOMUX_SW_MUX_Type
;typedef struct
{volatile unsigned int DRAM_ADDR00
;volatile unsigned int DRAM_ADDR01
;volatile unsigned int DRAM_ADDR02
;volatile unsigned int DRAM_ADDR03
;volatile unsigned int DRAM_ADDR04
;volatile unsigned int DRAM_ADDR05
;volatile unsigned int DRAM_ADDR06
;volatile unsigned int DRAM_ADDR07
;volatile unsigned int DRAM_ADDR08
;volatile unsigned int DRAM_ADDR09
;volatile unsigned int DRAM_ADDR10
;volatile unsigned int DRAM_ADDR11
;volatile unsigned int DRAM_ADDR12
;volatile unsigned int DRAM_ADDR13
;volatile unsigned int DRAM_ADDR14
;volatile unsigned int DRAM_ADDR15
;volatile unsigned int DRAM_DQM0
;volatile unsigned int DRAM_DQM1
;volatile unsigned int DRAM_RAS_B
;volatile unsigned int DRAM_CAS_B
;volatile unsigned int DRAM_CS0_B
;volatile unsigned int DRAM_CS1_B
;volatile unsigned int DRAM_SDWE_B
;volatile unsigned int DRAM_ODT0
;volatile unsigned int DRAM_ODT1
;volatile unsigned int DRAM_SDBA0
;volatile unsigned int DRAM_SDBA1
;volatile unsigned int DRAM_SDBA2
;volatile unsigned int DRAM_SDCKE0
;volatile unsigned int DRAM_SDCKE1
;volatile unsigned int DRAM_SDCLK0_P
;volatile unsigned int DRAM_SDQS0_P
;volatile unsigned int DRAM_SDQS1_P
;volatile unsigned int DRAM_RESET
;volatile unsigned int TEST_MODE
;volatile unsigned int POR_B
;volatile unsigned int ONOFF
;volatile unsigned int SNVS_PMIC_ON_REQ
;volatile unsigned int CCM_PMIC_STBY_REQ
;volatile unsigned int BOOT_MODE0
;volatile unsigned int BOOT_MODE1
;volatile unsigned int SNVS_TAMPER0
;volatile unsigned int SNVS_TAMPER1
;volatile unsigned int SNVS_TAMPER2
;volatile unsigned int SNVS_TAMPER3
;volatile unsigned int SNVS_TAMPER4
;volatile unsigned int SNVS_TAMPER5
;volatile unsigned int SNVS_TAMPER6
;volatile unsigned int SNVS_TAMPER7
;volatile unsigned int SNVS_TAMPER8
;volatile unsigned int SNVS_TAMPER9
;volatile unsigned int JTAG_MOD
;volatile unsigned int JTAG_TMS
;volatile unsigned int JTAG_TDO
;volatile unsigned int JTAG_TDI
;volatile unsigned int JTAG_TCK
;volatile unsigned int JTAG_TRST_B
;volatile unsigned int GPIO1_IO00
;volatile unsigned int GPIO1_IO01
;volatile unsigned int GPIO1_IO02
;volatile unsigned int GPIO1_IO03
;volatile unsigned int GPIO1_IO04
;volatile unsigned int GPIO1_IO05
;volatile unsigned int GPIO1_IO06
;volatile unsigned int GPIO1_IO07
;volatile unsigned int GPIO1_IO08
;volatile unsigned int GPIO1_IO09
;volatile unsigned int UART1_TX_DATA
;volatile unsigned int UART1_RX_DATA
;volatile unsigned int UART1_CTS_B
;volatile unsigned int UART1_RTS_B
;volatile unsigned int UART2_TX_DATA
;volatile unsigned int UART2_RX_DATA
;volatile unsigned int UART2_CTS_B
;volatile unsigned int UART2_RTS_B
;volatile unsigned int UART3_TX_DATA
;volatile unsigned int UART3_RX_DATA
;volatile unsigned int UART3_CTS_B
;volatile unsigned int UART3_RTS_B
;volatile unsigned int UART4_TX_DATA
;volatile unsigned int UART4_RX_DATA
;volatile unsigned int UART5_TX_DATA
;volatile unsigned int UART5_RX_DATA
;volatile unsigned int ENET1_RX_DATA0
;volatile unsigned int ENET1_RX_DATA1
;volatile unsigned int ENET1_RX_EN
;volatile unsigned int ENET1_TX_DATA0
;volatile unsigned int ENET1_TX_DATA1
;volatile unsigned int ENET1_TX_EN
;volatile unsigned int ENET1_TX_CLK
;volatile unsigned int ENET1_RX_ER
;volatile unsigned int ENET2_RX_DATA0
;volatile unsigned int ENET2_RX_DATA1
;volatile unsigned int ENET2_RX_EN
;volatile unsigned int ENET2_TX_DATA0
;volatile unsigned int ENET2_TX_DATA1
;volatile unsigned int ENET2_TX_EN
;volatile unsigned int ENET2_TX_CLK
;volatile unsigned int ENET2_RX_ER
;volatile unsigned int LCD_CLK
;volatile unsigned int LCD_ENABLE
;volatile unsigned int LCD_HSYNC
;volatile unsigned int LCD_VSYNC
;volatile unsigned int LCD_RESET
;volatile unsigned int LCD_DATA00
;volatile unsigned int LCD_DATA01
;volatile unsigned int LCD_DATA02
;volatile unsigned int LCD_DATA03
;volatile unsigned int LCD_DATA04
;volatile unsigned int LCD_DATA05
;volatile unsigned int LCD_DATA06
;volatile unsigned int LCD_DATA07
;volatile unsigned int LCD_DATA08
;volatile unsigned int LCD_DATA09
;volatile unsigned int LCD_DATA10
;volatile unsigned int LCD_DATA11
;volatile unsigned int LCD_DATA12
;volatile unsigned int LCD_DATA13
;volatile unsigned int LCD_DATA14
;volatile unsigned int LCD_DATA15
;volatile unsigned int LCD_DATA16
;volatile unsigned int LCD_DATA17
;volatile unsigned int LCD_DATA18
;volatile unsigned int LCD_DATA19
;volatile unsigned int LCD_DATA20
;volatile unsigned int LCD_DATA21
;volatile unsigned int LCD_DATA22
;volatile unsigned int LCD_DATA23
;volatile unsigned int NAND_RE_B
;volatile unsigned int NAND_WE_B
;volatile unsigned int NAND_DATA00
;volatile unsigned int NAND_DATA01
;volatile unsigned int NAND_DATA02
;volatile unsigned int NAND_DATA03
;volatile unsigned int NAND_DATA04
;volatile unsigned int NAND_DATA05
;volatile unsigned int NAND_DATA06
;volatile unsigned int NAND_DATA07
;volatile unsigned int NAND_ALE
;volatile unsigned int NAND_WP_B
;volatile unsigned int NAND_READY_B
;volatile unsigned int NAND_CE0_B
;volatile unsigned int NAND_CE1_B
;volatile unsigned int NAND_CLE
;volatile unsigned int NAND_DQS
;volatile unsigned int SD1_CMD
;volatile unsigned int SD1_CLK
;volatile unsigned int SD1_DATA0
;volatile unsigned int SD1_DATA1
;volatile unsigned int SD1_DATA2
;volatile unsigned int SD1_DATA3
;volatile unsigned int CSI_MCLK
;volatile unsigned int CSI_PIXCLK
;volatile unsigned int CSI_VSYNC
;volatile unsigned int CSI_HSYNC
;volatile unsigned int CSI_DATA00
;volatile unsigned int CSI_DATA01
;volatile unsigned int CSI_DATA02
;volatile unsigned int CSI_DATA03
;volatile unsigned int CSI_DATA04
;volatile unsigned int CSI_DATA05
;volatile unsigned int CSI_DATA06
;volatile unsigned int CSI_DATA07
;volatile unsigned int GRP_ADDDS
;volatile unsigned int GRP_DDRMODE_CTL
;volatile unsigned int GRP_B0DS
;volatile unsigned int GRP_DDRPK
;volatile unsigned int GRP_CTLDS
;volatile unsigned int GRP_B1DS
;volatile unsigned int GRP_DDRHYS
;volatile unsigned int GRP_DDRPKE
;volatile unsigned int GRP_DDRMODE
;volatile unsigned int GRP_DDR_TYPE
;
}IOMUX_SW_PAD_Type
;
typedef struct
{volatile unsigned int DR
; volatile unsigned int GDIR
; volatile unsigned int PSR
; volatile unsigned int ICR1
; volatile unsigned int ICR2
; volatile unsigned int IMR
; volatile unsigned int ISR
; volatile unsigned int EDGE_SEL
;
}GPIO_Type
;
#define CCM ((CCM_Type *)CCM_BASE)
#define CCM_ANALOG ((CCM_ANALOG_Type *)CCM_ANALOG_BASE)
#define IOMUX_SW_MUX ((IOMUX_SW_MUX_Type *)IOMUX_SW_MUX_BASE)
#define IOMUX_SW_PAD ((IOMUX_SW_PAD_Type *)IOMUX_SW_PAD_BASE)
#define GPIO1 ((GPIO_Type *)GPIO1_BASE)
#define GPIO2 ((GPIO_Type *)GPIO2_BASE)
#define GPIO3 ((GPIO_Type *)GPIO3_BASE)
#define GPIO4 ((GPIO_Type *)GPIO4_BASE)
#define GPIO5 ((GPIO_Type *)GPIO5_BASE)
在編寫寄存器組結構體的時候注意寄存器的地址是否連續,有些外設的寄存器地址可能不是連續的,會有一些保留地址,因此我們需要在結構體中留出這些保留的寄存器。
比如 CCM 的CCGR6 寄存器地址為 0X020C4080,而寄存器 CMEOR 的地址為 0X020C4088。按照地址順序遞增的原理,寄存器 CMEOR 的地址應該是 0X020C4084,但是實際上 CMEOR 的地址是0X020C4088,相當于中間跳過了 0X020C4088-0X020C4080=8 個字節,如果寄存器地址連續的話應該只差 4 個字節(32 位),但是現在差了 8 個字節,所以需要在寄存器 CCGR6 和 CMEOR直接加入一個保留寄存器,這就是第 47 行 RESERVED_3[1]的來源。如果不添加保留為來占位的話就會導致寄存器地址錯位!
2.main.c
#include "imx6ul.h"
void clk_enable(void)
{CCM
->CCGR0
=0xFFFFFFFF;CCM
->CCGR1
=0xFFFFFFFF;CCM
->CCGR2
=0xFFFFFFFF;CCM
->CCGR3
=0xFFFFFFFF;CCM
->CCGR4
=0xFFFFFFFF;CCM
->CCGR5
=0xFFFFFFFF;CCM
->CCGR6
=0xFFFFFFFF;}
void led_init(void)
{IOMUX_SW_MUX
->GPIO1_IO03
=0x5; IOMUX_SW_PAD
->GPIO1_IO03
=0x10B0;GPIO1
->GDIR
=0x8;GPIO1
->DR
=0x0;}
void delay_short(volatile unsigned int n
)
{while(n
--){}}
void delay(volatile unsigned int n
)
{while (n
--){delay_short(0x7ff);}}
void led_on(void)
{GPIO1
->DR
&= ~(1<<3); }
void led_off(void )
{GPIO1
->DR
|= (1<<3);
}
int main()
{clk_enable(); led_init(); while(1){led_off(); delay(500);led_on();delay(500);}return 0;
}
3.start.s
.global _start
.global _bss_start
_bss_start
:.word __bss_start
.global _bss_end
_bss_end
:.word __bss_end_start
:mrs r0
,cpsr bic r0
,r0
,#
0x1f orr r0
,r0
,#
0x13 msr cpsr
,r0 ldr r0
, _bss_startldr r1
, _bss_endmov r2
, #
0bss_loop
: stmia r0
!, {r2
}cmp r0
, r1 ble bss_loop ldr sp
,=0x80200000b main
4.編譯下載驗證
1.編寫鏈接腳本
將代碼段、數據段等鏈接到指定的地址中去。
SECTIONS
{. = 0x87800000;.text
:{start
.o
*(.text
)}.rodata
ALIGN(4) : {*(.rodata
*)}.data
ALIGN(4) : {*(.data
)}__bss_start
= .;.bss
ALIGN(4) : { *(.bss
) *(COMMON
)}__bss_end
= .;
}
2.編寫Makefile腳本
objs
:= start
.o main
.o
gcc
:=arm
-linux
-gnueabihf
-gcc
ld
:=arm
-linux
-gnueabihf
-ld
objcopy
:=arm
-linux
-gnueabihf
-objcopy
objdump
:=arm
-linux
-gnueabihf
-objdumpledc
.bin
: $
(objs
)$
(ld
) -Timx6ul
.lds
-o ledc
.elf $
^$
(objcopy
) -O binary
-S ledc
.elf $@$
(objdump
) -D
-m arm ledc
.elf
> ledc
.dis
%.o
: %.s$
(gcc
) -Wall
-nostdlib
-c
-O2
-o $@ $
<%.o
: %.c$
(gcc
) -Wall
-nostdlib
-c
-O2
-o $@ $
<clean
:rm
-rf
*.o ledc
.elf ledc
.bin ledc
.dis
3.編譯下載
使用 Make 命令編譯代碼,編譯成功以后使用軟件 imxdownload 將編譯完成的 ledc.bin 文件下載到 SD 卡中,命令如下:
chmod
777 imxdownload
./imxdownload ledc
.bin
/dev
/sdd
燒寫成功以后將 SD 卡插到開發板的 SD 卡槽中,然后復位開發板,如果代碼運行正常的話 LED0 就會以 500ms 的時間間隔亮滅。
具體過程請參考前幾篇博文
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的ARM(IMX6U)裸机模仿STM32驱动开发实验(定义外设结构体)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。