S5PV210裸机(二):看门狗,栈,icache,SoC时钟,重加载,led

看门狗
        电子设备会跑飞或者死机,需要设备自动复位,看门狗是SoC内部定时器,规定时间内需要重新置位,如果没有系统会被强制复位
WTCON(0xE2700000),bit5是开关:0关,1开

 

汇编设置栈和调用C
        C运行过程中局部变量需要栈,如果汇编没有设置栈地址,局部变量会落空,程序崩溃
系统在复位后默认是SVC模式,设置栈时不设置所有栈而是设置自己模式下的栈
        CPU启动,外部DRRAM未初始化,内部SRAM使用,SRAM内存做SVC栈

        SVC栈置为0xd0037D80(满减栈)

初始化iCache
        cache是内存高速缓存,打开icache后程序运行加快
        容量:CPU < 寄存器 < cache < DDR
        速度:CPU >  寄存器 > cache > DDR

        汇编读写cp15开关icache
                mrc p15,0,r0,c1,c0,0      // 读出cp15的c1到r0中
                bic r0, r0, #(1<<12)      // bit12 置0  关icache
                orr r0, r0, #(1<<12)      // bit12 置1  开icache
                mcr p15,0,r0,c1,c0,0

重定位和链接
        位置无关编码(PIC):汇编源文件编码成二进制可执行程序时编码方式与位置(内存地址)无关
        位置有关编码:汇编源码编码成二进制可执行程序后和内存地址是有关
        链接地址:链接时指定的地址,Makefile中-Ttext或链接脚本指定
        运行地址:程序实际运行地址,运行时被加载到的内存位置
        位置有关代码执行时运行地址和编译链接地址必须相同
        重定位是在运行地址处执行位置无关码,位置无关码从运行地址拷贝到链接地址处
        注意:210运行时地址是0xd0020010,指定的链接地址与运行地址不同时,内部SRAM射到0x0地址,故程序运行正常

        长跳转与短跳转     
                长跳转:ldr pc, = func
                短跳转:bl led_blink
                链接地址和运行地址相同,短跳转和长跳转无差异
                链接地址和运行地址不同,短跳转在运行地址,长跳转在链接地址处

        adr与伪指令ldr
                ldr是长加载,adr是短加载
                adr加载运行时地址,ldr加载链接地址
                adr和ldr可以判断是否需要重定位

        程序段
                代码段:(.text)文本段
                数据段:(.data)
                bss段:(.bss),ZI段
                自己定义段

        链接脚本
                链接脚本:段名,地址(作为链接地址的内存地址)
                SECTIONS {}  整个链接脚本
                .            当前位置
                =            赋值

SoC时钟
        时钟是同步工作系统的同步节拍,SoC内部器件需要同步时钟系统指挥
        210获得时钟:外部晶振+内部时钟发生器+内部PLL产生高频时钟(1GHz、1.2GHz)+内部分频器分频

        210的时钟
                时钟域:MSYS、DSYS、PSYS
                MSYS: CPU(Cortex-A8内核)、DRAM控制器(DMC0和DMC1)、IRAM&IROM等
                DSYS: 都是和视频显示、编解码等有关的模块等
                PSYS: 和内部的各种外设时钟有关,譬如串口、SD接口、I2C、AC97、USB等
                时钟来源:晶振+时钟发生器+PLL+分频电路
                210外部有4个晶振接口,接晶振后上电相应模块振荡产生原始时钟,原始时钟经过筛选进入PLL电路生成高频时钟,再经分频到各模块

 

        PLL
                PLL:APLL、MPLL、VPLL
                APLL:Cortex-A8内核 MSYS域
                MPLL&EPLL:DSYS PSYS
                VPLL:Video视频相关模块

        210时钟域
                MSYS
                        ARMCLK:cpu内核时钟(主频)
                        HCLK_MSYS:MSYS域高频时钟(DMC0和DMC1)
                        PCLK_MSYS:MSYS域低频时钟
                        HCLK_IMEM:iMEM(iROM和iRAM)
                DSYS
                        HCLK_DSYS:DSYS域高频时钟
                        PCLK_DSYS:DSYS域低频时钟
                PSYS
                        HCLK_PSYSPSYS域的高频时钟
                        PCLK_PSYS:PSYS域的低频时钟
                SCLK_ONENAND
                注意:210内部外设接在(内部AMBA总线)总线上,AMBA总线高频分支AHB,低频分支APB

        时钟典型值
                210上电默认外部晶振+内部时钟发生器产生24MHz时钟给ARMCLK,iROM初始化时钟系统
                freq(ARMCLK)         = 1000 MHz
                freq(HCLK_MSYS)      = 200 MHz
                freq(HCLK_IMEM)      = 100 MHz
                freq(PCLK_MSYS)      = 100 MHz
                freq(HCLK_DSYS)      = 166 MHz
                freq(PCLK_DSYS)      = 83 MHz
                freq(HCLK_PSYS)      = 133 MHz
                freq(PCLK_PSYS)      = 66 MHz
                freq(SCLK_ONENAND)   = 133 MHz, 166 MHz

        时钟设置寄存器
                xPLL_LOCK:控制PLL锁定周期


                xPLL_CON/xPLL_CON0/xPLL_CON1:打开/关闭PLL电路,设置PLL倍频参数,查看PLL锁定状态


                 三类寄存器CON、SRC、DIV,CON决定PLL倍频,SRC决定来源,DIV决定分频 

                CLK_SRCn(n:0~6):设置时钟来源(MUX开关)


                CLK_SRC_MASKn:MUX(n选1),默认进开关开放

         

       CLK_DIVn:各模块分频器参数配置


                CLK_GATE_x:分频出开关控制

 


                CLK_DIV_STATn和CLK_MUX_STATn:查看DIV和MUX状态(完成或进行)
              

 

        时钟设置
                选择不使用PLL,24MHz原始时钟接入绕过APLL(走FINAPLL)
                设置锁定时间,默认0x0FFF,时钟系统有变化时缓冲时间
                设置分频系统
                设置PLL的倍频,ARMCLK(1GHz)
                打开PLL

        寄存器设置
                CLK_SRC设置MUX开关,设置全0(bit0和bit4为0),APLL和MPLL禁用
                CLK_LOCK设置PLL锁定延时,推荐值为0xFFF或0xFFFF
                CLK_DIV寄存器设置为0x14131440  00010100000100110001010001000000

                PCLK_PSYS = HCLK_PSYS / 2
                HCLK_PSYS = MOUT_PSYS / 5
                PCLK_DSYS = HCLK_DSYS / 2
                HCLK_DSYS = MOUT_DSYS / 4
                PCLK_MSYS = HCLK_MSYS /4
                HCLK_MSYS = ARMCLK / 5
                SCLKA2M = SCLKAPLL /5
                ARMCLK = MOUT_MSYS / 1

        APLL和MPLL设置M、P、S

 

 

LED 

 

 

demo: 

        关看门狗,初始化栈,初始化icache,初始化时钟,重加载方式实现流水灯

代码示例:

        start.S

#define WTCON		0xE2700000
#define SVC_STACK	0xd0037d80.global _start					
_start://关看门狗ldr r0, =WTCONldr r1, =0x0str r1, [r0]//初始化时钟bl clock_init//设置SVC栈ldr sp, =SVC_STACK//开/关icachemrc p15,0,r0,c1,c0,0;			// 读出cp15的c1到r0中//bic r0, r0, #(1<<12)			// bit12 置0  关icacheorr r0, r0, #(1<<12)			// bit12 置1  开icachemcr p15,0,r0,c1,c0,0;//重定位adr r0, _start  			//ldr指令用于加载_start的链接地址:0xd0024000ldr r1, =_start // bss段的起始地址ldr r2, =bss_start	cmp r0, r1			beq clean_bss		//拷贝
copy_loop:ldr r3, [r0], #4    // 源str r3, [r1], #4	// 目的   cmp r1, r2			bne copy_loop// 清bss段
clean_bss:ldr r0, =bss_start					ldr r1, =bss_endcmp r0, r1				// 如果r0等于r1则bss段为空beq run_on_dram			// 清除bss完之后的地址mov r2, #0
clear_loop:str r2, [r0], #4		cmp r0, r1				bne clear_looprun_on_dram:	//长跳转led_blinkldr pc, =led_blink				//调用C程序,bl指令实现短跳转//bl led_blink					b .

        led.c

#define GPJ0CON   0xE0200240
#define GPJ0DAT   0xE0200244#define rGPJ0CON  *((volatile unsigned int *)GPJ0CON)
#define rGPJ0DAT  *((volatile unsigned int *)GPJ0DAT)void delay_time()
{volatile unsigned int i = 900000;   while (i--);              
}void led_blink()
{// led初始化,设置GPJ0CON为输出模式rGPJ0CON = 0x11111111;while (1){// led亮rGPJ0DAT = ((0<<3) | (0<<4) | (0<<5));//延时delay_time();// led灭rGPJ0DAT = ((1<<3) | (1<<4) | (1<<5));}
}

clock_init.c

//时钟控制器基地址
#define ELFIN_CLOCK_POWER_BASE    0xE0100000  
//相关寄存器偏移
#define APLL_LOCK_OFFSET    0x00    
#define MPLL_LOCK_OFFSET    0x08
#define APLL_CON0_OFFSET    0x100
#define MPLL_CON_OFFSET     0x108
#define CLK_SRC0_OFFSET     0x200
#define CLK_SRC_MASK0_OFFSET  0x280
#define CLK_DIV0_OFFSET     0x300
#define CLK_DIV0_MASK     0x7fffffff#define APLL_MDIV           0x7d    // 125
#define APLL_PDIV           0x3
#define APLL_SDIV           0x1
#define MPLL_MDIV           0x29b   // 667
#define MPLL_PDIV           0xc
#define MPLL_SDIV           0x1#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
#define APLL_VAL      set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
#define MPLL_VAL      set_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)#define REG_CLK_SRC0  (ELFIN_CLOCK_POWER_BASE + CLK_SRC0_OFFSET)
#define REG_APLL_LOCK (ELFIN_CLOCK_POWER_BASE + APLL_LOCK_OFFSET)
#define REG_MPLL_LOCK (ELFIN_CLOCK_POWER_BASE + MPLL_LOCK_OFFSET)
#define REG_CLK_DIV0  (ELFIN_CLOCK_POWER_BASE + CLK_DIV0_OFFSET)
#define REG_APLL_CON0 (ELFIN_CLOCK_POWER_BASE + APLL_CON0_OFFSET)
#define REG_MPLL_CON  (ELFIN_CLOCK_POWER_BASE + MPLL_CON_OFFSET)#define rREG_CLK_SRC0 (*(volatile unsigned int *)REG_CLK_SRC0)
#define rREG_APLL_LOCK  (*(volatile unsigned int *)REG_APLL_LOCK)
#define rREG_MPLL_LOCK  (*(volatile unsigned int *)REG_MPLL_LOCK)
#define rREG_CLK_DIV0 (*(volatile unsigned int *)REG_CLK_DIV0)
#define rREG_APLL_CON0  (*(volatile unsigned int *)REG_APLL_CON0)
#define rREG_MPLL_CON (*(volatile unsigned int *)REG_MPLL_CON)void clock_init()
{//禁止PLLrREG_CLK_SRC0 = 0x0;//设置锁定时间rREG_APLL_LOCK = 0x0000ffff;rREG_MPLL_LOCK = 0x0000ffff;//设置分频rREG_CLK_DIV0 = 0x14131440;//设置PLL// FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHzrREG_APLL_CON0 = APLL_VAL;// FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHzrREG_MPLL_CON = MPLL_VAL;//使用PLLrREG_CLK_SRC0 = 0x10001111;
}

        link.lds

SECTIONS
{. = 0xd0024000;.text : {start.o* (.text)}.data : {* (.data)}bss_start = .; .bss : {* (.bss)}bss_end  = .;	
}

        Makefile

led.bin: start.o led.o clock.oarm-linux-ld -Tlink.lds -o led.elf $^arm-linux-objcopy -O binary led.elf led.binarm-linux-objdump -D led.elf > led_elf.disgcc mkv210_image.c -o mkx210./mkx210 led.bin 210.bin%.o : %.Sarm-linux-gcc -o $@ $< -c -nostdlib%.o : %.carm-linux-gcc -o $@ $< -c -nostdlibclean:rm *.o *.elf *.bin *.dis mkx210 -f	

        mkv210_image.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define BUFSIZE                 (16*1024)
#define IMG_SIZE                (16*1024)
#define SPL_HEADER_SIZE         16
//#define SPL_HEADER              "S5PC110 HEADER  "
#define SPL_HEADER              "****************"int main (int argc, char *argv[])
{FILE		    *fp;char		    *Buf, *a;int		        BufLen;int		        nbytes, fileLen;unsigned int	checksum, count;int		i;if (argc != 3){printf("Usage: %s <source file> <destination file>\n", argv[0]);return -1;}//分配16K的bufferBufLen = BUFSIZE;Buf = (char *)malloc(BufLen);if (!Buf){printf("Alloc buffer failed!\n");return -1;}memset(Buf, 0x00, BufLen);//读源bin到bufferfp = fopen(argv[1], "rb");if( fp == NULL){printf("source file open error\n");free(Buf);return -1;}//获取源bin长度fseek(fp, 0L, SEEK_END);								// 定位到文件尾fileLen = ftell(fp);									// 得到文件长度fseek(fp, 0L, SEEK_SET);								// 再次定位到文件头//源bin长度不得超过16K-16bytecount = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);//buffer[0~15]存放"S5PC110 HEADER  "memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);//读源bin到buffer[16]nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);if ( nbytes != count ){printf("source file read error\n");free(Buf);fclose(fp);return -1;}fclose(fp);//计算校验和a = Buf + SPL_HEADER_SIZE;for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)checksum += (0x000000FF) & *a++;//将校验和保存在buffer[8~15]a = Buf + 8;							*( (unsigned int *)a ) = checksum;//拷贝buffer中的内容到目的binfp = fopen(argv[2], "wb");if (fp == NULL){printf("destination file open error\n");free(Buf);return -1;}//将16k的buffer拷贝到目的bin中a = Buf;nbytes	= fwrite( a, 1, BufLen, fp);if ( nbytes != BufLen ){printf("destination file write error\n");free(Buf);fclose(fp);return -1;}free(Buf);fclose(fp);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/146571.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【VINS】苹果手机采集单目相机+IMU数据离线运行VINS-Mono

0.准备工作 开个新坑&#xff0c;之前用Android手机做过离线采集数据的实验&#xff0c;这次用IPhone来测试&#xff01; 1.虚拟机配置Mac OS 下载一个Mac OS 的ios镜像&#xff0c;打开虚拟机按照跟Ubuntu差不多的方式安装&#xff0c;但是发现没有Mac OS的入口。 因为VMwa…

前端两年半,CSDN创作一周年

文章目录 一、机缘巧合1.1、起因1.2、万事开头难1.3、 何以坚持&#xff1f; 二、收获三、日常四、憧憬 五、总结 一、机缘巧合 1.1、起因 最开始接触CSDN&#xff0c;还是因为同专业的同学&#xff0c;将计算机实验课的实验题&#xff0c;记录总结并发在了专业群里。后来正式…

【深入了解Java String类】

目录 String类 常用方法 字符串的不可变性 String的内存分析 StringBuilder类 解释可变和不可变字符串 常用方法 面试题&#xff1a;String&#xff0c;StringBuilder&#xff0c;StringBuffer之间的区别和联系 String类的OJ练习 String类 【1】直接使用&#xff0c…

Arcgis提取玉米种植地分布,并以此为掩膜提取遥感影像

Arcgis提取玉米种植地分布上&#xff0c;并以此为掩膜提取遥感影像 一、问题描述 因为之前反演是整个研究区&#xff0c;然而土地利用类型有很多类&#xff0c;只在农田或者植被上进行反演&#xff0c;需要去除水体、建筑等其他类型&#xff0c;如何处理得到下图中只有耕地类…

【新版】系统架构设计师 - 层次式架构设计理论与实践

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录 架构 - 层次式架构设计理论与实践考点摘要层次式体系结构概述表现层框架设计MVC模式MVP模式MVVM模式使用XML设计表现层表现层中UIP设计思想 中间层架构设计业务逻辑层工作流设计业务逻辑层设计 数据访问层…

热点文章采集-热点资讯采集工具免费

在信息时代&#xff0c;掌握热点资讯、了解热门时事、采集热门文章是许多自媒体从业者和信息追踪者的重要任务。然而&#xff0c;这并不是一项容易的任务。信息的海洋庞大而繁杂&#xff0c;要从中捞取有价值的热点和文章需要耗费大量时间和精力。 热点资讯采集&#xff1a;信息…

矢量图形编辑软件illustrator 2023 mac特点介绍

illustrator 2023 mac是一款矢量图形编辑软件&#xff0c;用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator mac软件特点 矢量图形&#xff1a;illustrator创建的图形是矢量图形&#xff0c;可以无限放大而不失真&#xff0c;这与像素图形编辑软件&am…

C语言实例_调用SQLITE数据库完成数据增删改查

一、SQLite介绍 SQLite是一种轻量级的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是一个开源的、零配置的、服务器端的、自包含的、零管理的、事务性的SQL数据库引擎。它被广泛应用于嵌入式设备、移动设备和桌面应用程序等领域。 SQLite的特点包括&…

【Java 进阶篇】MySQL启动与关闭、目录结构以及 SQL 相关概念

MySQL 服务启动与关闭 MySQL是一个常用的关系型数据库管理系统&#xff0c;通过启动和关闭MySQL服务&#xff0c;可以控制数据库的运行状态。本节将介绍如何在Windows和Linux系统上启动和关闭MySQL服务。 在Windows上启动和关闭MySQL服务 启动MySQL服务 在Windows上&#x…

掌动智能:替代JMeter的压力测试工具有哪些

JMeter是一个广泛使用的开源压力测试工具&#xff0c;但在实际应用中&#xff0c;也有一些其他优秀的替代品可供选择。本文将介绍几个可替代JMeter的压力测试工具&#xff0c;它们在功能、性能和易用性方面都具有独特优势&#xff0c;可以满足不同压力测试需求的选择。 一、Gat…

[Linux]线程互斥

[Linux]线程互斥 文章目录 [Linux]线程互斥线程并发访问问题线程互斥控制--加锁pthread_mutex_init函数pthread_mutex_destroy函数pthread_mutex_lock函数pthread_mutex_unlock函数锁相关函数使用示例使用锁的细节加锁解锁的实现原理 线程安全概念常见的线程不安全的情况常见的…

OpenCV之分水岭算法(watershed)

Opencv 中 watershed函数原型&#xff1a; void watershed( InputArray image, InputOutputArray markers ); 第一个参数 image&#xff0c;必须是一个8bit 3通道彩色图像矩阵序列&#xff0c;第一个参数没什么要说的。关键是第二个参数 markers&#xff0c;Opencv官方文档的说…

使用 Ruby 语言来解析开放文档格式 OOXML 文件

在这篇文章中&#xff0c;我们将了解一个开发团队如何解决他们在应用程序中解析数据时遇到的问题。 为了测试 ONLYOFFICE 文档编辑器&#xff0c;我们用Ruby语言开发编写了个docx、xlsx、pptx文件解析器程序&#xff0c;它是免费开源的&#xff0c;被我们放在GitHub和RubyGems…

【一】初步认识数据库

数据库概览数据库 缘起表(Table)的理解用表来定义数据库数据库系统的理解概念层次的理解实例层次的理解 数据库管理系统的理解从用户角度看从系统实现角度看典型的数据库管理系统 数据库语言数据库定义、操纵、控制语言数据库语言 VS 高级语言 内容回顾练习 数据库概览 走马观…

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗

在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用&#xff0c;原则上可…

深入学习git

1、git原理及整体架构图 一些常用的命令 git add . 或 git add src/com/ygl/hello/hello.java 指定文件 git commit . 或 git commit src/com/ygl/hello/hello.java 指定文件 git push origin 分支名称 2、git stash的应用场景 场景一&#xff1a;你正在当前分支A开发&…

localStorage实现历史记录搜索功能

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;JavaScript &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; 文章目录 为什么使用localStorage如何使用localStorage实现历史记录搜索功能&#xff08…

代码随想录算法训练营第五十二天 | 300. 最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

1. 最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; dp[i] 取决于 i 之前所有的dp class Solution {public int lengthOfLIS(int[] nums) {// dp[i] 第 0 - i 位的递增子序列长度int length nums.length;int[] dp new int[length];Arrays.fil…

基于SSM的微博系统网站的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

如何用ChatGPT学或教英文?5个使用ChatGPT的应用场景!

原文&#xff1a;百度安全验证 AI工具ChatGPT的出现大幅改变许多领域的运作方式&#xff0c;就连「学英文」也不例外&#xff01;我发现ChatGPT应用在英语的学习与教学上非常有意思。 究竟ChatGPT如何改变英文学习者(学生)与教学者(老师)呢&#xff1f; 有5个应用场景我感到…