在嵌入式裸机开发种,需要准确操作每个寄存器。直接定义每个寄存器,往往不好使用。用结构体将所有相关的寄存器进行结构化管理。使用基地址加偏移的方式,在不连续的地方用占位留空,这种方式十分方便。下面用这种方式定义I.MX6U的一部分寄存器。
代码部分
imx6ul.h 定义寄存器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
| #define CCM_BASE (0X020c4000) #define CCM_ANALOG_BASE (0X020C8000) #define IOMUX_SW_MUX_BASE (0X020E0044) #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 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)
|
main.c led灯结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include "imx6ul.h"
void clk_enable(void) { CCM->CCGR0 = 0XFFFFFFFFUL; CCM->CCGR1 = 0XFFFFFFFFUL; CCM->CCGR2 = 0XFFFFFFFFUL; CCM->CCGR3 = 0XFFFFFFFFUL; CCM->CCGR4 = 0XFFFFFFFFUL; CCM->CCGR5 = 0XFFFFFFFFUL; CCM->CCGR6 = 0XFFFFFFFFUL; }
void led_init(void) { IOMUX_SW_MUX->GPIO1_IO03 = 0X5; IOMUX_SW_PAD->GPIO1_IO03 = 0x10B0; GPIO1->GDIR = 0X00000008; GPIO1->DR &= ~(1<<3); }
void led_on(void) { GPIO1->DR &= ~(1<<3); }
void led_off(void) { GPIO1->DR |= (1<<3); }
void delay_short(volatile unsigned int n) { while (n--) { } }
void delay(volatile unsigned int n) { while (n--) { delay_short(0x7ff); } }
int main(void) { clk_enable(); led_init(); while (1) { led_off(); delay(500); led_on(); delay(500); } }
|
start.s 汇编代码 初始化c语言环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| .global _start .global _bss_start .global _bss_end _bss_start: .word __bss_start _bss_end: .word __bss_end
_start: mrs r0,cpsr bic r0,r0,#0x1f orr r0,r0,#0x13 msr cpsr, r0 /*清除bss段*/ ldr r0,_bss_start ldr r1,_bss_end mov r2,#0 bss_loop: stmia r0!,{r2} cmp r0,r1 @比较R0和R1 ble bss_loop @R0地址小于R1,继续清除bss段
/*设置sp指针*/ ldr sp,=0x80200000 b main
|
Makefile文件 自动编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| objs := start.o main.o
ledc.bin:$(objs) arm-linux-gnueabihf-ld -Timxdownload.lds -o ledc.elf $^ arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@ arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
%.o:%.s arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o:%.S arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o:%.c arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
clean: rm -rf *.o ledc.bin ledc.elf ledc.dis
|
imx6ul.lds 链接文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SECTIONS{ . = 0X87800000; .text : { start.o main.o *(.text) } .rodata ALIGN(4) : {*(.rodata*)} .data ALIGN(4) : {*(.data)} /*4字节对齐,定义数据段*/ __bss_start = .; /*bss段的起始地址赋值定位符*/ .bss ALIGN(4) : {*(.bss)*(COMMON)} /*定义bss段*/ __bss_end = .; /*bss段的结束地址赋值定位符*/ }
|
总结
使用这种结构进行编写的好处就是能够更加清晰地找出需要的寄存器,工程管理起来更加方便。
主要有三个要点
根据手册依次完成上面三个部分的编写。