TX2440 ARM开发板Uboot移植(二、让u-boot从nandFlash动起来)

2024-06-04 09:32

本文主要是介绍TX2440 ARM开发板Uboot移植(二、让u-boot从nandFlash动起来),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接上:让u-boot从norFlash动起来


完成上面工作后,u-boot中还没有对2440上Nand Flash的支持,以及u-boot从Nand Flash上启动,这些得我们一步步去实现了。

1、修改配置文件 include/configs/smdk2440.h :

1.1、新增宏 CONFIG_CMD_NAND (大概在95行)
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_ENV

1.2、在文件的最后面增加3个宏:

//NAND flash settings
#define NAND_CTL_BASE     0x4E000000  //NAND Flash的地址
#define CFG_MAX_NAND_DEVICE  1         //NAND Flash设备数目为1
#define NAND_MAX_CHIPS      1                 //每个NAND设备由1个NADN芯片组成

2、  修改 include/s3c24x0.h 文件,增加S3C2440_NAND数据结构(168行)

/* NAND FLASH (see S3C2440 manual chapter 6) */
typedef struct {
    S3C24X0_REG32 NFCONF;
    S3C24X0_REG32 NFCONT;
    S3C24X0_REG32 NFCMD;
    S3C24X0_REG32 NFADDR;
    S3C24X0_REG32 NFDATA;
    S3C24X0_REG32 NFMECCD0;
    S3C24X0_REG32 NFMECCD1;
    S3C24X0_REG32 NFSECCD;
    S3C24X0_REG32 NFSTAT;
    S3C24X0_REG32 NFESTAT0;
    S3C24X0_REG32 NFESTAT1;
    S3C24X0_REG32 NFMECC0;
    S3C24X0_REG32 NFMECC1;
    S3C24X0_REG32 NFSECC;
    S3C24X0_REG32 NFSBLK;
    S3C24X0_REG32 NFEBLK;
} /*__attribute__((__packed__))*/ S3C2440_NAND;

3、u-boot默认是从Nor Flash启动的。修改文件 cpu/arm920t/start.S ,使u-boot可以从Nand Flash启动:

对文件改动较大,仔细对比源代码,主要的修改是将栈的初始化放到前面,用于后面调用C函数的需要;
判断u-boot不是从内存启动后,调用CopyCode2Ram函数,实现把启动代码拷贝到内存

/*
  * we do sys-critical inits only at reboot,
  * not when booting from ram!
  */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
 adr r0, _start    /* r0 <- current position of code   */
 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */
 cmp     r0, r1        /* don't reloc during debug         */
 blne cpu_init_crit
#endif

stack_setup:      //将栈的初始化放到前面
 ldr r0, _TEXT_BASE     /* upper 128 KiB: relocated uboot   */
 sub r0, r0, #CFG_MALLOC_LEN  /* malloc area                   */
 sub r0, r0, #CFG_GBL_DATA_SIZE  /* bdinfo              */
#ifdef CONFIG_USE_IRQ
 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
 sub sp, r0, #12  /* leave 3 words for abort-stack    */

relocate:      /* relocate U-Boot to RAM     */
 adr r0, _start  /* r0 <- current position of code   */
 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */
 cmp     r0, r1                  /* don't reloc during debug         */
 beq     clear_bss

 ldr r2, _armboot_start
 ldr r3, _bss_start
 sub r2, r3, r2  /* r2 <- size of armboot            */
 bl CopyCode2Ram   
// 调用board/smdk2440/boot_Init.c里的CopyCode2Ram函数,把启动代码拷贝到内存

clear_bss:
 ldr r0, _bss_start  /* find start of bss segment        */
 ldr r1, _bss_end  /* stop here                        */
 mov r2, #0x00000000  /* clear                            */
clbss_l:str r2, [r0]  /* clear loop...                    */
 add r0, r0, #4
 cmp r0, r1
 ble clbss_l

 ldr pc, _start_armboot

_start_armboot: .word start_armboot

4、新建 board/smdk2440/boot_Init.c 文件,实现从NandFlsh读取字节;判断启动方式,并拷贝启动代码到内存。代码如下:

#include <common.h>
#include <s3c2440.h>

#define BUSY            1

#ifdef NAND_LARGEPAGE
#define NAND_SECTOR_SIZE 2048
#else
#define NAND_SECTOR_SIZE 512
#endif
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)

/* 供外部调用的函数 */
void nand_init_ll(void);
void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size);

/* S3C2440的NAND Flash处理函数 */
static void nand_reset(void);
static void wait_idle(void);
static void nand_select_chip(void);
static void nand_deselect_chip(void);
static void write_cmd(int cmd);
static void write_addr(unsigned int addr);
static unsigned char read_data(void);
/* S3C2440的NAND Flash操作函数 */
/* 复位 */

static void nand_reset(void)
{
    nand_select_chip();
    write_cmd(0xff);  // 复位命令
    wait_idle();
    nand_deselect_chip();
}

/* 等待NAND Flash就绪 */
static void wait_idle(void)
{
  int i;
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;

 while(!(*p & BUSY))
 for(i=0; i<10; i++);
}

/* 发出片选信号 */
static void nand_select_chip(void)
{
 int i;
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

 s3c2440nand->NFCONT &= ~(1<<1);
 for(i=0; i<10; i++);    
}

/* 取消片选信号 */
static void nand_deselect_chip(void)
{
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
    s3c2440nand->NFCONT |= (1<<1);
}

/* 发出命令 */
static void write_cmd(int cmd)
{
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
    *p = cmd;
}

/* 发出地址 Nand进行寻址的部分*/
static void write_addr(unsigned int addr)
{
  int i;
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
#ifndef NAND_LARGEPAGE    
 *p = addr & 0xff;
 for(i=0; i<10; i++);
 *p = (addr >> 9) & 0xff;
 for(i=0; i<10; i++);
 *p = (addr >> 17) & 0xff;
 for(i=0; i<10; i++);
 *p = (addr >> 25) & 0xff;
 for(i=0; i<10; i++);
#else
 int col, page;
 col = addr & NAND_BLOCK_MASK;
 page = addr / NAND_SECTOR_SIZE;
 *p = col & 0xff;   /* Column Address A0~A7 */
 for(i=0; i<10; i++);  
 *p = (col >> 8) & 0x0f;  /* Column Address A8~A11 */
 for(i=0; i<10; i++);
 *p = page & 0xff;   /* Row Address A12~A19 */
 for(i=0; i<10; i++);
 *p = (page >> 8) & 0xff; /* Row Address A20~A27 */
 for(i=0; i<10; i++);
 *p = (page >> 16) & 0x03; /* Row Address A28~A29 */
 for(i=0; i<10; i++);
#endif
}

/* 读取数据 */
static unsigned char read_data(void)
{
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
 volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
 return *p;
}

/* 初始化NAND Flash */
void nand_init_ll(void)
{
 S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

#define TACLS   0
#define TWRPH0  3
#define TWRPH1  0
 /* 设置时序 */
 s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
 /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
 s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
 /* 复位NAND Flash */
 nand_reset();
}

/* 读函数 */
void nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;
    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return ;    /* 地址或长度不对齐 */
    }
    /* 选中芯片 */
    nand_select_chip();
    for(i=start_addr; i < (start_addr + size);) {
      /* 发出READ0命令 */
      write_cmd(0);
      /* Write Address */
      write_addr(i);
#ifdef NAND_LARGEPAGE
 write_cmd(0x30);
#endif
      wait_idle();
      for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
          *buf = read_data();
          buf++;
      }
    }
    /* 取消片选信号 */
    nand_deselect_chip();
    return ;
}

int bBootFrmNORFlash(void)   /* 取OM0、1的值,判断开发板是从NorFlash还是NandFlash启动 */
{
  volatile unsigned int *bwsCON = (volatile unsigned int *)0x48000000;
  unsigned int bwsVal;
  bwsVal = *bwsCON;
  bwsVal &= 0x06;
  if (bwsVal==0){
   return 0;
  }
  else {
   return 1;
  }
}

int CopyCode2Ram(unsigned long start_addr, unsigned char *buf, int size)
{
    unsigned int *pdwDest;
    unsigned int *pdwSrc;
    int i;

    if (bBootFrmNORFlash())
    {
      pdwDest = (unsigned int *)buf;
      pdwSrc  = (unsigned int *)start_addr;
      /* 从 NOR Flash启动 */
      for (i = 0; i < size / 4; i++)
      {
        pdwDest[i] = pdwSrc[i];
      }
    }
    else
    {
      /* 初始化NAND Flash */
   nand_init_ll();
      /* 从 NAND Flash启动 */
      nand_read_ll(buf, start_addr, (size + NAND_BLOCK_MASK)&~(NAND_BLOCK_MASK));
    }
 return 0;
}

注意:上面这段代码中对Nand进行寻址的部分,这跟具体的Nand Flash的寻址方式有关。根据开发板上的Nand Flash(K9F1208U0C)数据手册得知,片内寻址是采用26位地址形式。从第0位开始分四次通过I/O0-I/O7进行传送,并进行片内寻址。具体含义和结构图如下(相关概念参考Nand数据手册):
TX2440 ARM开发板Uboot移植(二、让u-boot从nandFlash动起来) - xiesnap - 谢烨

5、在 board/smdk2440/Makefile 中添加 boot_Init.c 的编译选项,使他编译到u-boot中:

COBJS    := my2440.o flash.o boot_Init.o

6、还有一个重要的地方要修改,在 cpu/arm920t/u-boot.lds 中,这个u-boot启动连接脚本文件决定了u-boot运行的入口地址,以及各个段的存储位置,这也是链接定位的作用。添加下面两行代码,主要目的是防止编译器把CopyCode2Ram的子函数放到4K之后,否则是无法启动的。如下:

.text :
{
      cpu/arm920t/start.o    (.text)
      board/smdk2440/boot_Init.o (.text)
      board/smdk2440/lowlevel_init.o (.text)    
      *(.text)
}

这篇关于TX2440 ARM开发板Uboot移植(二、让u-boot从nandFlash动起来)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1029700

相关文章

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

RabbitMQ使用及与spring boot整合

1.MQ   消息队列(Message Queue,简称MQ)——应用程序和应用程序之间的通信方法   应用:不同进程Process/线程Thread之间通信   比较流行的中间件:     ActiveMQ     RabbitMQ(非常重量级,更适合于企业级的开发)     Kafka(高吞吐量的分布式发布订阅消息系统)     RocketMQ   在高并发、可靠性、成熟度等

Spring Boot 入门篇

一、简介 Spring Boot是一款开源的Java Web应用框架,旨在简化Spring应用的初始搭建以及开发过程。它整合了Spring技术栈中的诸多关键组件,为开发者提供了一种快速、简便的Spring应用开发方式。Spring Boot遵循“约定优于配置”的原则,通过自动配置、起步依赖和内置的Servlet容器,极大地简化了传统Spring应用的配置和部署过程。 二、Spring Boot

Spring Boot集成Tess4J实现OCR

1.什么是Tess4j? Tesseract是一个开源的光学字符识别(OCR)引擎,它可以将图像中的文字转换为计算机可读的文本。支持多种语言和书面语言,并且可以在命令行中执行。它是一个流行的开源OCR工具,可以在许多不同的操作系统上运行。Tess4J是一个基于Tesseract OCR引擎的Java接口,可以用来识别图像中的文本,说白了,就是封装了它的API,让Java可以直接调用。 Tess

部署若依Spring boot项目

nohup和& nohup命令解释 nohup命令:nohup 是 no hang up 的缩写,就是不挂断的意思,但没有后台运行,终端不能标准输入。nohup :不挂断的运行,注意并没有后台运行的功能,就是指,用nohup运行命令可以使命令永久的执行下去,和用户终端没有关系,注意了nohup没有后台运行的意思;&才是后台运行在缺省情况下该作业的所有输出都被重定向到一个名为nohup.o

开发板NFS挂载文件目录

文章目录 序NFS1. 安装 NFS 服务器和客户端在服务器上(NFS 服务器端)在客户端上(NFS 客户端) 2. 配置 NFS 服务器创建共享目录编辑 `/etc/exports` 文件启动 NFS 服务 3. 在客户端挂载 NFS 共享创建挂载点挂载 NFS 共享验证挂载 4. 设置开机自动挂载5. 解决权限问题 序 本节主要实现虚拟机(服务器)与开发板(客户端)通过N

使用Spring Boot集成Spring Data JPA和单例模式构建库存管理系统

引言 在企业级应用开发中,数据库操作是非常重要的一环。Spring Data JPA提供了一种简化的方式来进行数据库交互,它使得开发者无需编写复杂的JPA代码就可以完成常见的CRUD操作。此外,设计模式如单例模式可以帮助我们更好地管理和控制对象的创建过程,从而提高系统的性能和可维护性。本文将展示如何结合Spring Boot、Spring Data JPA以及单例模式来构建一个基本的库存管理系统

Spring Boot集成PDFBox实现电子签章

概述 随着无纸化办公的普及,电子文档的使用越来越广泛。电子签章作为一种有效的身份验证方式,在很多场景下替代了传统的纸质文件签名。Apache PDFBox 是一个开源的Java库,可以用来渲染、生成、填写PDF文档等操作。本文将介绍如何使用Spring Boot框架结合PDFBox来实现电子签章功能。 准备工作 环境搭建:确保你的开发环境中安装了JDK 8或更高版本,并且配置好了Maven或