解决Unable to handle kernel NULL pointer dereference

执行make zImage生成zImage,将zImage下载到mini2440开发板中,出现错误:

S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c24xx-nand s3c2440-nand: Tacls=4, 39ns Twrph0=8 79ns, Twrph1=8 79ns
Unable to handle kernel NULL pointer dereference at virtual address 00000018
pgd = c0004000
[00000018] *pgd=00000000
Internal error: Oops: 5 [#1]
经过分析:找不到NAND flash的地址。

三星的NAND的时序为:

S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns

与调试的信息不符合,在drivers/mtd/nand/中查找NAND的驱动s3c2410.c,

static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
{
 struct s3c2410_platform_nand *plat = info->platform;
 int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
 int tacls, twrph0, twrph1;
 unsigned long clkrate = clk_get_rate(info->clk);
 unsigned long uninitialized_var(set), cfg, uninitialized_var(mask);
 unsigned long flags;

 /* calculate the timing information for the controller */

 info->clk_rate = clkrate;
 clkrate /= 1000; /* turn clock into kHz for ease of use */

 if (plat != NULL) {
  tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
  twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
  twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
 } else {
  /* default timings */
  tacls = tacls_max;
  twrph0 = 8;
  twrph1 = 8;
 }

 if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
  dev_err(info->device, "cannot get suitable timings\n");
  return -EINVAL;
 }

 dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
        tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));

 switch (info->cpu_type) {
 case TYPE_S3C2410:
  mask = (S3C2410_NFCONF_TACLS(3) |
   S3C2410_NFCONF_TWRPH0(7) |
   S3C2410_NFCONF_TWRPH1(7));
  set = S3C2410_NFCONF_EN;
  set |= S3C2410_NFCONF_TACLS(tacls - 1);
  set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
  set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
  break;

 case TYPE_S3C2440:
 case TYPE_S3C2412:
  mask = (S3C2440_NFCONF_TACLS(tacls_max - 1) |
   S3C2440_NFCONF_TWRPH0(7) |
   S3C2440_NFCONF_TWRPH1(7));

  set = S3C2440_NFCONF_TACLS(tacls - 1);
  set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
  set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
  break;

 default:
  BUG();
 }

 local_irq_save(flags);

 cfg = readl(info->regs + S3C2410_NFCONF);
 cfg &= ~mask;
 cfg |= set;
 writel(cfg, info->regs + S3C2410_NFCONF);

 local_irq_restore(flags);

 dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);

 return 0;
}

上述文件并没有使用我们在mach-s3c2440.c中我们为NAND 初始化的信息mini2440_nand_info,而是使用了默认配置

 {
  /* default timings */
  tacls = tacls_max;
  twrph0 = 8;
  twrph1 = 8;
 }

所以我们在static void __init mini2440_machine_init(void)中添加

s3c_device_nand.dev.platform_data=&mini2440_nand_info;

将我们配置的信息传递给驱动。

重新编译,下载内核,一切OK。

s3c_device_nand.dev.platform_data=&mini2440_nand_info;

你可能感兴趣的:(解决Unable to handle kernel NULL pointer dereference)