首页 > 其他分享 >C语言bringup LED

C语言bringup LED

时间:2024-03-16 22:57:50浏览次数:11  
标签:GPIO1 LED bringup 代码段 C语言 start PAD 设置 led

参考文章:https://doc.embedfire.com/linux/imx6/driver/zh/latest/bare_metal/gcc_led.html   LED灯源码程序包含两部分内容,第一部分在汇编文件中设置“栈地址”并执行跳转命令跳转到main函数执行C代码。 第二部分在C文件中使led灯不断闪烁。 将“汇编点亮led灯的源码led.S复制到”更名为start.S。 在start.S的基础上增加“栈”设置和执行跳转指令,如下所示。 C语言版LED bringup代码:

 /***********************第一部分*********************/
  .text            //代码段
  .align 2         //设置字节对齐
  .global _start   //定义全局变量

  _start:          //程序的开始
    b reset      //跳转到reset标号处

      reset:
      bic r0, r0, #0x1f /* 将 r0 的低 5 位清零,也就是 cpsr 的 M0~M4 */
      orr r0, r0, #0x13 /* r0 或上 0x13,表示使用 SVC 模式 */
      msr cpsr, r0 /* 将 r0 的数据写入到 cpsr_c 中 */

  /***********************第二部分*********************/
      ldr sp, =0x84000000   //设置栈地址64M
      b main                //跳转到main函数

  /***********************第三部分*******************/
    /*跳转到light_led函数*/
    //   bl light_led
    /*进入死循环*/
  loop:
      b loop

 

c语言代码:
// 时钟控制寄存器
#define CCM_CCGR1 (volatile unsigned long*)0x20C406C
//GPIO1_04复用功能选择寄存器
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04 (volatile unsigned long*)0x20E006C
//PAD属性设置寄存器
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO04 (volatile unsigned long*)0x20E02F8
//GPIO方向设置寄存器
#define GPIO1_GDIR (volatile unsigned long*)0x0209C004
//GPIO输出状态寄存器
#define GPIO1_DR (volatile unsigned long*)0x0209C000

#define uint32_t  unsigned int

/*简单延时函数*/
void delay(uint32_t count)
{
   volatile uint32_t i = 0;
   for (i = 0; i < count; ++i)
   {
      __asm("NOP"); /* 调用nop空指令 */
   }
}

int main()
{
   *(CCM_CCGR1) = 0xFFFFFFFF;                     //开启GPIO1的时钟
   *(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04) = 0x5;     //设置PAD复用功能为GPIO
   *(IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO04) = 0x1F838; //设置PAD属性
   *(GPIO1_GDIR) = 0x10;                          //设置GPIO为输出模式
   *(GPIO1_DR) = 0x0;                             //设置输出电平为低电平

   while(1)                // 不断改变RGB红灯所在引脚的高低电平
   {
      *(GPIO1_DR) = 0x0;
      delay(0xFFFFF);
      *(GPIO1_DR) = 1<<4;
      delay(0xFFFFF);
   }
   return 0;
}

 

编写链接脚本: 写好的代码(无论是汇编还是C语言)都要经过编译、汇编、链接等步骤生成二进 制文件或者可供下载的文件。在编译阶编译器会对每个源文件进行语法检查并生成对应的汇编语言, 汇编是将汇编文件转化为机器码。在上一章我们使用”arm-none-eabi-gcc -g -c led.S -o led.o”命令 完成了源码的编译、汇编工作,生成了.o文件。编译和汇编是针对单个源文件, 也就编译完成后一个源文件(.c,.S或.s)对应一个.o文件。程序链接阶段就会将这些.o链接成一个文件。 链接脚本的作用就是告诉编译器怎么链接这些文件,比如那个文件放在最前面,程序的代码段、数据段、bss段分别放在什么位置等等。 链接脚本可参考:https://www.cnblogs.com/lethe1203/p/18077801 c语言bringup led的链接脚本如下:
 ENTRY(_start)
 SECTIONS {
   . = 0x87800000;

   . = ALIGN(4);
   .text :
   {
   start.o (.text)
   *(.text)
   }

   . = ALIGN(4);
   .data :
   {
   *(.data)
   }

   . = ALIGN(4);
   .bss :
   {
   *(.bss)
   }
 }
  • 第1行,ENTRY(_start) 用于指定程序的入口,ENTRY( )是设置入口地址的命令, “_start”是程序的入口,本章的led程序的入口地址位于start.S的“_start”标号处。
  • 第2行,定义SECTIONS。SECTIONS可以理解为是一块区域,我们在这块区域排布我们的代码, 链接时链接器就会按照这里的指示链接我们的代码。
  • 第3行,“.”运算符代表当前位置。 我们在SECTION的最开始使用“.= 0x87800000”就是将链接起始地址设置为0x87800000。
  • 第5行,设置字节对齐。这里同样用到了“.”运算符,它表示从当前位置开始执行四字节对齐。
  • 第6行,定义代码段。“.text :”用于定义代码段,固定的语法要求,我们按照要求写即可。 在“{}”中指定那些内容放在代码段。
  • 第8-9行,将start.o中的代码放到代码段的最前面。start.S是启动代码应当首先被执行, 所以通常情况下要把它放到代码段的最前面,其他源文件的代码按照系统默认的排放顺序即可, 通配符“*”在这里表示其他剩余所有的.o文件。
  • 第12-16行,设置数据段。同设置代码段类似,首先设置字节对齐,然后定义代码段。在代码段里使用“*”通配符, 将所有源文件中的代码添加到这个代码段中。
  • 第18-22行,设置BSS段。设置方法与设置数据段完全相同
 

标签:GPIO1,LED,bringup,代码段,C语言,start,PAD,设置,led
From: https://www.cnblogs.com/lethe1203/p/18077807

相关文章

  • C语言快速入门之字符函数和字符串函数
    一.字符分类函数和字符转换函数C语言中有一系列的函数专门做字符分类的,就是区分一个字符是属于什么类型的,头文件是#include<ctype.h>以下是具体函数:这些函数的使用方法类似,我们写出一些代码来举例。例如,我们实验以下islower()函数,它是接受一个字符,如果是⼩写字⺟就返回......
  • 汇编bringup LED
    此节学习视频:https://www.bilibili.com/video/BV1yE411h7uQ?p=6&vd_source=432ba293ecfc949a4174ab91ccc526d6 在STM32上,.s就是汇编,cortexA一般不会提供汇编,必须自己写汇编文件,对于A系列,初始化ram,没办法用c初始化,必须先初始化一些外设,这些外设必须用汇编初始化,但是用到的汇编......
  • 【C语言步行梯】各类操作符、类型转换与原码、反码、补码详谈
    ......
  • 【提升C语言基础知识】数据在内存中的存储
    1.整数在内存中的存储1.1原码,反码,补码整数(占4个字节,即32个bit)的二进制表示方法有3种,即原码,反码,补码,三种表示方法均有符号位和数值位两部分原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码反码:将原码符号位(最高位,0为正,1为负)不变,其余位按位取反得到反码补码:反码......
  • C语言解决几个常见问题
    文章目录1.数组操作2.交换数组3.求字符串的逆序排序(1)非递归的(2)递归的4.计算一个数的每位之和(递归实现)5.递归实现n的k次方1.数组操作创建一个整形数组,完成对数组的操作实现函数init()初始化数组为全0实现print()打印数组的每个元素实现reverse()函数完成数组......
  • 输入8个整数元素存入数组中,再输入一个整数n,在数组中查找,找到了返回数组元素的下标,找不
    #include<stdio.h>intmain(){inti,n,arr[8];//Input8integerelementsintothearrayprintf("Enter8integerelements:\n");for(i=0;i<8;i++){scanf("%d",&arr[i]);}......
  • 详细解释可变参数列表C语言
    目录考研复习-函数栈帧(详解)一.什么是可变参数列表?1.1 求两个数据中的最大值1.2求多个数据中的最大值1.3逐步分析 1.va_start 2.va_arg3.va_end 4._INTSIZEOF(t)第一步理解:4的倍数第二步理解:最小4字节对齐数                第三步理解:理解源代......
  • 【C语言】结构体
    ......
  • 实验1 C语言开发环境使用和数据类型,运算符,表达式
    #include<stdio.h>intmain(){printf("O\n");printf("<H>\n");printf("II\n");return0;}#include<stdio.h>intmain(){printf("O\n");printf("<H>\n");print......
  • C语言基础-2、字符类型
    一、字符类型char是一种整数,也是一种特殊的类型:字符。这是因为:用单引号表示的字符字面量:'a','1'''也是一个字符printf和scanf里用%c来输入输出字符1、字符的输入输出#include<stdio.h>intmain(){ charc,d; c=1; d='1'; if(c==d){ printf("相等\n"); }......