这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 第七章之S5PV210移植到Nandflash

共2条 1/1 1 跳转至

第七章之S5PV210移植到Nandflash

高工
2018-04-04 08:20:00     打赏

1,之前的操作都是基于SD卡进行运行的,如今在Nandfalsh中运行u-boot.因为s5p_goni.h配置文件没有配置Nand相关文件,所以先配置Nand文件.

在include/configs/s5p_goni.h中添加一个:#define CONFIG_CMD_NAND

2,根据board_init_r函数中nand_init()如下图:

3,进行nand_init();

4,所以配置文件还需要添加#defnie CONFIG_SYS_MAX_NAND_DEVICE  1,及其 nand基地址#define CONFIG_SYS_NAND_BASE  0xB0E00000

 

5,查看common/Makefie如图:先把环境变量设成nand

 

6,在nand_init()中,发现drives/mtd/nand/没有相关的board_nand_init()函数.根据s3c2410修改成s5pv210nand.c:

复制代码

/*************************************************************************
> File Name: s5pv210_nand.c
> Author: 
> Mail: 
> Created Time: Wed 09 Aug 2017 03:34:27 PM CST
************************************************************************/
/* name:Sourcelink 
* (C) Copyright 2006 OpenMoko, Inc.

* Author: Harald Welte <laforge@openmoko.org>


* SPDX-License-Identifier: GPL-2.0+ 
*/ 

#include <common.h> 

#include <nand.h> 
#include <asm/arch/nand_reg.h> 
#include <asm/io.h> 

#define MP0_1CON (*(volatile unsigned long *)0xE02002E0) 
#define MP0_3CON (*(volatile unsigned long *)0xE0200320) 
#define MP0_6CON (*(volatile unsigned long *)0xE0200380) 

/* Nand Flash Configuration Register */ 
#define AddrCycle 1 /* 5 address cycle */ 
#define PageSize 0 /* 2KBytes/Page */ 
#define MLCFlash 0 /* SLC NAND Flash */ 
#define TWRPH1 1 /* (0+1) * 7.5 > 5ns (tCLH/tALH) */ 
#define TWRPH0 2 /* (1+1) * 7.5ns > 12ns (tWP) */ 
#define TACLS 1 /* 7.5ns * 2 > 12ns tALS tCLS */ 

/* Control Register */ 
#define MODE 1 /* ENABLE NAND Flash Controller */ 
#define Reg_nCE0 1 /* Disable chip select */ 

/* modied by Sourcelink */ 
static void s5pv210_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) 

struct nand_chip *chip = mtd->priv; 
struct s5pv210_nand *nand = (struct s5pv210_nand *)s5pv210_get_base_nand(); 
debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl); 
ulong IO_ADDR_W = (ulong)nand; 
if (ctrl & NAND_CTRL_CHANGE) { 

if (ctrl & NAND_CLE) 
IO_ADDR_W = IO_ADDR_W | 0x8; /* Command Register */ 
else if (ctrl & NAND_ALE) 
IO_ADDR_W = IO_ADDR_W | 0xC; /* Address Register */ 

chip->IO_ADDR_W = (void *)IO_ADDR_W; 

if (ctrl & NAND_NCE) /* select */ 
writel(readl(&nand->nfcont) & ~(1 << 1), &nand->nfcont); 
else /* deselect */ 
writel(readl(&nand->nfcont) | (1 << 1), &nand->nfcont); 


if (cmd != NAND_CMD_NONE) 
writeb(cmd, chip->IO_ADDR_W); 
else 
chip->IO_ADDR_W = &nand->nfdata; 



static int s5pv210_dev_ready(struct mtd_info *mtd) 

struct s5pv210_nand *nand = (struct s5pv210_nand *)s5pv210_get_base_nand(); 
debug("dev_ready\n"); 
return readl(&nand->nfstat) & 0x01; 


#ifdef CONFIG_S3C2410_NAND_HWECC 
void s5pv210_nand_enable_hwecc(struct mtd_info *mtd, int mode) 

struct s5pv210_nand *nand = (struct s5pv210_nand *)s5pv210_get_base_nand(); 
debug("s5pv210_nand_enable_hwecc(%p, %d)\n", mtd, mode); 
writel(readl(&nand->nfconf) | S3C2410_NFCONF_INITECC, &nand->nfconf); 


static int s5pv210_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, 
u_char *ecc_code) 

struct s5pv210_nand *nand = (struct s5pv210_nand *)s5pv210_get_base_nand(); 
ecc_code[0] = readb(&nand->nfecc); 
ecc_code[1] = readb(&nand->nfecc + 1); 
ecc_code[2] = readb(&nand->nfecc + 2); 
debug("s5pv210_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n", 
mtd , ecc_code[0], ecc_code[1], ecc_code[2]); 

return 0; 


static int s5pv210_nand_correct_data(struct mtd_info *mtd, u_char *dat, 
u_char *read_ecc, u_char *calc_ecc) 

if (read_ecc[0] == calc_ecc[0] && 
read_ecc[1] == calc_ecc[1] && 
read_ecc[2] == calc_ecc[2]) 
return 0; 

printf("s5pv210_nand_correct_data: not implemented\n"); 
return -1; 

#endif 

/* 
* add by Sourcelink 
* nand_select_chip 
* @mtd: MTD device structure 
* @ctl: 0 to select, -1 for deselect 

* Default select function for 1 chip devices. 
*/ 
static void s5pv210_nand_select_chip(struct mtd_info *mtd, int ctl) 

struct nand_chip *chip = mtd->priv; 

switch (ctl) { 
case -1: /* deselect the chip */ 
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); 
break; 
case 0: /* Select the chip */ 
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); 
break; 

default: 
BUG(); 



/* modied by Sourcelink */ 
int board_nand_init(struct nand_chip *nand) 

u32 cfg; 
struct s5pv210_nand *nand_reg = (struct s5pv210_nand *)(struct s5pv210_nand *)s5pv210_get_base_nand(); 

debug("board_nand_init()\n"); 

/* initialize hardware */ 
/* HCLK_PSYS=133MHz(7.5ns) */ 
cfg = ((AddrCycle << 1) | (PageSize << 2) | (MLCFlash << 3) | (TWRPH1 << 4) | (TWRPH0 << 8) | (TACLS << 12)); 

writel(cfg, &nand_reg->nfconf); 

writel((Reg_nCE0 << 1) | (MODE << 0), &nand_reg->nfcont); 
/* Disable chip select and Enable NAND Flash Controller */ 

/* 
* port map 
* CE1-> Xm0CSn2 -> MP01_2 
* CLE-> Xm0FCLE -> MP03_0 
* ALE-> Xm0FALE -> MP03_1 
* WE -> Xm0FWEn -> MP03_2 
* RE -> Xm0FREn -> MP03_3 
* R/B1->Xm0FRnB0-> MP03_4 
* IO[7:0]->Xm0DATA[7:0]->MP0_6[7:0] 
* */ 

/* 设置片选引脚 CSN[0] */ 
MP0_1CON &= ~(0x00000F00); 
MP0_1CON |= (3 << 8); 

/* CLE,ALE,WE,RE,R/B1 */ 
MP0_3CON &= ~(0x000FFFFF); 
MP0_3CON |= 0x00022222; 

/* DATA */ 
MP0_6CON = 0x22222222; 

/* initialize nand_chip data structure */ 
nand->IO_ADDR_R = (void *)&nand_reg->nfdata; 
nand->IO_ADDR_W = (void *)&nand_reg->nfdata; 

nand->select_chip = s5pv210_nand_select_chip; 

/* read_buf and write_buf are default */ 
/* read_byte and write_byte are default */ 

/* hwcontrol always must be implemented */ 
nand->cmd_ctrl = s5pv210_hwcontrol; 

nand->dev_ready = s5pv210_dev_ready; 

#ifdef CONFIG_S3C2410_NAND_HWECC 
nand->ecc.hwctl = s5pv210_nand_enable_hwecc; 
nand->ecc.calculate = s5pv210_nand_calculate_ecc; 
nand->ecc.correct = s5pv210_nand_correct_data; 
nand->ecc.mode = NAND_ECC_HW; 
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE; 
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES; 
nand->ecc.strength = 1; 
#else 
nand->ecc.mode = NAND_ECC_SOFT; 
#endif 

#ifdef CONFIG_S3C2410_NAND_BBT 
nand->bbt_options |= NAND_BBT_USE_FLASH; 
#endif 

debug("end of nand_init\n"); 

return 0; 
}



复制代码
7,在vim arch/arm/include/asm/arch-s5pc1xx/cpu.h  下添加:

在62行添加#define S5PV210_NAND_BASE       0xB0E00000

 

8,然后在arch/arm/include/asm/arch-s5pc1xx/下创建文件nand_reg.h,定义 NAND 的寄存器结构体

复制代码

/*************************************************************************
> File Name: nand_reg.h
> Author: 
> Mail: 
> Created Time: Wed 09 Aug 2017 04:11:49 PM CST
************************************************************************/


#ifndef _NAND_REG_H
#define _NAND_REG_H



#ifndef __ASSEMBLY__ 
static inline struct s5pv210_nand *s5pv210_get_base_nand(void)
{
return (struct s5pv210_nand *)S5PV210_NAND_BASE;


struct s5pv210_nand { 
unsigned int nfconf; 
unsigned int nfcont; 
unsigned int nfcmmd; 
unsigned int nfaddr; 
unsigned int nfdata; 
unsigned int nfmeccd0; 
unsigned int nfmeccd1; 
unsigned int nfseccd; 
unsigned int nfsblk; 
unsigned int nfeblk; 
unsigned int nfstat; 
unsigned int nfeccerr0; 
unsigned int nfeccerr1; 
unsigned int nfmecc0; 
unsigned int nfmecc1; 
unsigned int nfsecc; 
unsigned int nfmlcbitpt; 
}; 

#endif 
#endif

 
复制代码

9,修改drivers/mtd/nand/Makefile,将s5pv210_nand.c编译进uboot

 10,添加环境变量偏移量,在配置文件里添加:#define CONFIG_ENV_OFFSET,移植NAND,必需要OFFSET

 

11,然后,再make,生成可以移值到Nand falsh的u-boot.




专家
2018-04-04 08:56:58     打赏
2楼

谢谢楼主分享。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]