历史上的今天
返回首页

历史上的今天

今天是:2024年10月13日(星期日)

正在发生

2018年10月13日 | JZ2440裸板之系统时钟和UART实验

2018-10-13 来源:eefocus

启动程序源码head.S:

@******************************************************************************

@ File:head.S

@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行

@******************************************************************************       

   

.extern     main

.text 

.global _start 

_start:

Reset:                  

    ldr sp, =4096                      @ 设置栈指针,以下都是C函数,调用前需要设好栈

    bl  disable_watch_dog      @ 关闭WATCHDOG,否则CPU会不断重启

    // bl是位置无关码,相当于:PCnew = PC + 偏移

    //                                           PCnew = (4+8) + 0x28 = 0x34

    //ldr pc, =disable_watch_dog  这一条指令即为位置相关的,用绝对地址(链接地址)跳转

    

    bl  clock_init                                        @ 设置MPLL,改变FCLK、HCLK、PCLK

    bl  memsetup                                      @ 设置存储控制器以使用SDRAM

    bl  copy_steppingstone_to_sdram     @ 复制代码到SDRAM中

    ldr pc, =on_sdram                               @ 跳到SDRAM中继续执行

on_sdram:

    ldr sp, =0x34000000     @ 设置栈指针

    ldr lr, =halt_loop           @ 设置返回地址

    ldr pc, =main                @ 调用main函数

halt_loop:

    b   halt_loop

=====================================================================

init.c源码:

// init.c: 进行一些初始化

#include "s3c24xx.h"

 

void disable_watch_dog(void);

void clock_init(void);

void memsetup(void);

void copy_steppingstone_to_sdram(void);

// 关闭WATCHDOG,否则CPU会不断重启

void disable_watch_dog(void)

{

    WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可

}

#define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))

#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))

// 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV

// 有如下计算公式:

//  S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)

//  S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)

//  其中: m = MDIV + 8, p = PDIV + 2, s = SDIV

// 对于本开发板,Fin = 12MHz

// 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,

// FCLK=200MHz,HCLK=100MHz,PCLK=50MHz

 

void clock_init(void)

{

    // LOCKTIME = 0x00ffffff;   // 使用默认值即可

    CLKDIVN  = 0x03;                // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1

    // 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” 

__asm__(

    "mrc    p15, 0, r1, c1, c0, 0\n"        // 读出控制寄存器  

    "orr    r1, r1, #0xc0000000\n"        // 设置为“asynchronous bus mode” 

    "mcr    p15, 0, r1, c1, c0, 0\n"        // 写入控制寄存器 

    );

    // 判断是S3C2410还是S3C2440 

    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))

    {

        MPLLCON = S3C2410_MPLL_200MHZ;  // 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz 

    }

    else

    {

        MPLLCON = S3C2440_MPLL_200MHZ;  // 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz 

    }       

}

// 设置存储控制器以使用SDRAM

void memsetup(void)

{

    volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

    // 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值

    // 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到

    // SDRAM之前就可以在steppingstone中运行

     

    // 存储控制器13个寄存器的值 

    p[0] = 0x22011110;     //BWSCON

    p[1] = 0x00000700;     //BANKCON0

    p[2] = 0x00000700;     //BANKCON1

    p[3] = 0x00000700;     //BANKCON2

    p[4] = 0x00000700;     //BANKCON3  

    p[5] = 0x00000700;     //BANKCON4

    p[6] = 0x00000700;     //BANKCON5

    p[7] = 0x00018005;     //BANKCON6

    p[8] = 0x00018005;     //BANKCON7    

                            

    // HCLK=12MHz:  0x008C07A3,

    // HCLK=100MHz: 0x008C04F4                                              

    p[9]  = 0x008C04F4;     //REFRESH

    

    p[10] = 0x000000B1;     //BANKSIZE

    p[11] = 0x00000030;     //MRSRB6

    p[12] = 0x00000030;     //MRSRB7

}

void copy_steppingstone_to_sdram(void)

{

    unsigned int *pdwSrc  = (unsigned int *)0;

    unsigned int *pdwDest = (unsigned int *)0x30000000;

    

    while (pdwSrc < (unsigned int *)4096)

    {

        *pdwDest = *pdwSrc;

        pdwDest++;

        pdwSrc++;

    }

}

=====================================================================

serial.h源码:

void uart0_init(void);

void putc(unsigned char c);

unsigned char getc(void);

int isDigit(unsigned char c);

int isLetter(unsigned char c);

=====================================================================

serial.c源码:

#include "s3c24xx.h"

#include "serial.h"

#define TXD0READY   (1<<2)

#define RXD0READY   (1)

#define PCLK                50000000           // init.c中的clock_init函数设置PCLK为50MHz

#define UART_CLK        PCLK                  //  UART0的时钟源设为PCLK

#define UART_BAUD_RATE  115200      // 波特率

#define UART_BRD        ((UART_CLK  / (UART_BAUD_RATE * 16)) - 1)

// 初始化UART0

// 115200,8N1,无流控

void uart0_init(void)

{

    GPHCON  |= 0xa0;           // GPH2,GPH3用作TXD0,RXD0

    GPHUP   = 0x0c;              // GPH2,GPH3内部上拉

    ULCON0  = 0x03;             // 8N1(8个数据位,无较验,1个停止位)

    UCON0   = 0x05;             // 查询方式,UART时钟源为PCLK

    UFCON0  = 0x00;            // 不使用FIFO

    UMCON0  = 0x00;          // 不使用流控

    UBRDIV0 = UART_BRD;  // 波特率为115200

}

// 发送一个字符

void putc(unsigned char c)

{

    // 等待,直到发送缓冲区中的数据已经全部发送出去 

    while (!(UTRSTAT0 & TXD0READY));

    

    // 向UTXH0寄存器中写入数据,UART即自动将它发送出去 

    UTXH0 = c;

}

// 接收字符

unsigned char getc(void)

{

    // 等待,直到接收缓冲区中的有数据 

    while (!(UTRSTAT0 & RXD0READY));

    

    // 直接读取URXH0寄存器,即可获得接收到的数据 

    return URXH0;

}

// 判断一个字符是否数字

int isDigit(unsigned char c)

{

    if (c >= '0' && c <= '9')

        return 1;

    else

        return 0;       

}

// 判断一个字符是否英文字母

int isLetter(unsigned char c)

{

    if (c >= 'a' && c <= 'z')

        return 1;

    else if (c >= 'A' && c <= 'Z')

        return 1;       

    else

        return 0;

}

=====================================================================

main.c源码:

#include "serial.h"

int main()

{

    unsigned char c;

    uart0_init();   // 波特率115200,8N1(8个数据位,无校验位,1个停止位)

    while(1)

    {

        // 从串口接收数据后,判断其是否数字或子母,若是则加1后输出

        c = getc();

        if (isDigit(c) || isLetter(c))

            putc(c+1);

    }

    return 0;

}

=====================================================================

Makefile文件:

objs := head.o init.o serial.o main.o

uart.bin: $(objs)

    arm-linux-ld -Tuart.lds -o uart_elf $^

    arm-linux-objcopy -O binary -S uart_elf $@

    arm-linux-objdump -D -m arm uart_elf > uart.dis

    

%.o:%.c

    arm-linux-gcc -Wall -O2 -c -o $@ $<

%.o:%.S

    arm-linux-gcc -Wall -O2 -c -o $@ $<

clean:

    rm -f uart.bin uart_elf uart.dis *.o        

=====================================================================

uart.lds文件:

SECTIONS {

    . = 0x30000000;

    .text            : { *(.text) }

    .rodata ALIGN(4) : {*(.rodata)} 

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

    .bss ALIGN(4)    : { *(.bss)  *(COMMON) }

}


推荐阅读

史海拾趣

Cermetek Microelectronics公司的发展小趣事

Cermetek Microelectronics公司在创立之初,便专注于微电子技术的研发与创新。创始人凭借在半导体领域的深厚背景,带领团队攻克了一系列技术难题,成功开发出具有高性能和稳定性的微电子产品。这些产品不仅满足了市场对微型化、高集成度的需求,更在多个关键领域实现了技术突破,为公司赢得了市场的初步认可。

Ferranti Electric Inc公司的发展小趣事

随着技术的不断发展和创新,Ferranti Electric Inc公司在电气领域取得了显著的成就。特别是在设计和制造用于恶劣气候或关键安全领域的复杂、高可靠性电气产品方面,公司展示了其卓越的技术实力。这些产品不仅广泛应用于军用领域,同时也为民用领域提供了大量电气产品解决方案。公司的全球影响力逐渐扩大,产品远销世界各地。

Ark-Les Connectors公司的发展小趣事

随着公司规模的扩大和产品线的丰富,Ark-Les Connectors公司开始积极寻求市场拓展。公司制定了针对不同区域和行业的市场拓展策略,通过参加国际电子展会、建立销售网络、开展合作伙伴计划等方式,不断扩大品牌影响力。同时,公司还根据市场需求调整产品策略,推出定制化解决方案,满足不同客户的个性化需求。这些举措使得Ark-Les的市场占有率稳步提升,公司业绩也实现了稳步增长。

Conexcon Group公司的发展小趣事

随着全球化进程的加速,Conexcon Group积极实施国际化战略,将业务拓展至海外市场。公司通过在海外设立研发中心和生产基地,进一步提升了自身的研发能力和生产效率。同时,公司还加强了与国际知名品牌的合作,通过共同推广和营销活动,提升了自身品牌在国际市场的知名度和影响力。这些举措不仅为公司带来了丰厚的利润回报,也为公司的长远发展奠定了坚实的基础。

DAQ Electronics LLC公司的发展小趣事

随着技术的不断成熟和产品线的丰富,DAQ Electronics LLC公司开始积极拓展市场。公司通过与科研机构、高校以及企业建立合作关系,将数据采集技术应用于更多领域。在科学研究领域,DAQ Electronics LLC公司的数据采集设备为实验数据的准确获取提供了有力保障;在工业生产领域,其设备则帮助企业实现了对生产过程的实时监控和数据分析。

EBK Kruger GmbH & Co KG公司的发展小趣事

面对数字化浪潮的挑战,EBK Kruger积极拥抱数字化转型。公司引入了先进的ERP系统和智能制造技术,提高了生产效率和产品质量。同时,EBK Kruger还加强了对大数据和人工智能技术的研发和应用,为客户提供了更加智能化和个性化的产品和服务。通过数字化转型的推动,EBK Kruger在激烈的市场竞争中保持了领先地位。

问答坊 | AI 解惑

TVS普及贴

TVS中文说明,写得不错。适合新手学习,老手温习。…

查看全部问答>

初学嵌入式应该看哪些书

学校发的是:嵌入式微处理结构与应用 由浅入深还应该看哪些书? 请推荐一下。…

查看全部问答>

请教嵌入式LINUX下GPRS模块连接Internet

现在使用的是SIMCOM700模块,我们产品除了要实现在打电话和发短信功能外,还在支持浏览器上网,从网上查了一些资料,如果要通过GPRS上网了话,连接GPRS后,还需要进行PPP协议交互。PPP协议这块我们准备自个来做,但还有一些疑问不太清晰,本来对这 ...…

查看全部问答>

请高手指点嵌入式软件工程师 (linux)开发驱动的三个问题(可以是基于ARM平台的)

我查了点招聘网上的资料感觉还是迷糊,我总结了下有以下几点 熟悉linux kernel 熟悉进程间通讯(ipc) 线程互斥  socket编程  熟悉掌握linux下各种gnu编程工具的使用方法 如gcc obcopy gdb 等 这个只是招聘上的启示 1、 ...…

查看全部问答>

DALLAS系列IC/MCU/单片机/芯片解密

DALLAS系列IC/MCU/单片机/芯片解密 未尽型号,请来电咨询!张工:13760303660 DS87C520 DS87C250 DS89C530 DS87C2520 DS87C320 FDS8958A DS89C21 ...... …

查看全部问答>

怎么实现对PC机CMOS全部地址内容的访问?

RTRT 貌似实现对CMOS低64字节的访问直接调用outportb和inportb函数即可,但是却不能访问到更高字节的数据(强行访问256个字节就会每64个字节出现一组数据的循环),不知道大家有什么方法访问CMOS全部地址呢?…

查看全部问答>

要学习51,是买学习板还是自己焊比较好呢?

要学习51,是买学习板还是自己焊比较好呢?自己焊是在万用板上焊的吧?…

查看全部问答>

在EVC中开发Dialog程序,想让它一启动就最大化

上面要留出菜单栏,下面要留出状态栏,就中间一块区域。。谢谢帮忙…

查看全部问答>

stm32电脑触摸屏

                                 为课程设计做一个stm32为控制芯片的触摸屏控制,并与计算机的USB通信,将普通电脑变成一触摸屏的电脑。请问一下这 ...…

查看全部问答>