技术标签: u-boot
https://github.com/SourceLink/S5PV210
1、修改堆栈指针
vim include/configs/smdkv210.h
#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_SDRAM_BASE + 0x40000000 /* modied by Sourcelink */
#define CONFIG_SYS_INIT_SP_ADDR CONFIG_SYS_LOAD_ADDR /* modied by Sourcelink */
#define CONFIG_SYS_SDRAM_BASE 0x20000000 /* modied by Sourcelink */
2、添加串口
a)添加串口初始化引脚代码
vim board/samsung/smdkv210/lowlevel_init.S
ldr r0, =0xE0200000
ldr r1, =0X22222222
str r1, [r0]
b)添加串口初始化配置代码
vim drivers/serial/serial_s5p.c
/*
* (C) Copyright 2009 SAMSUNG Electronics
* Minkyu Kang <[email protected]>
* Heungjun Kim <[email protected]>
*
* based on drivers/serial/s3c64xx.c
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <fdtdec.h>
#include <linux/compiler.h>
#include <asm/io.h>
#include <asm/arch/uart.h>
#include <asm/arch/clk.h>
#include <serial.h>
DECLARE_GLOBAL_DATA_PTR;
#define RX_FIFO_COUNT_MASK 0xff
#define RX_FIFO_FULL_MASK (1 << 8)
#define TX_FIFO_FULL_MASK (1 << 24)
/* Information about a serial port */
struct fdt_serial {
u32 base_addr; /* address of registers in physical memory */
u8 port_id; /* uart port number */
u8 enabled; /* 1 if enabled, 0 if disabled */
} config __attribute__ ((section(".data")));
static inline struct s5p_uart *s5p_get_base_uart(int dev_index)
{
#ifdef CONFIG_OF_CONTROL
return (struct s5p_uart *)(config.base_addr);
#else
u32 offset = dev_index * sizeof(struct s5p_uart);
return (struct s5p_uart *)(samsung_get_base_uart() + offset);
#endif
}
/*
* The coefficient, used to calculate the baudrate on S5P UARTs is
* calculated as
* C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT
* however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1,
* 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants:
*/
static const int udivslot[] = {
0,
0x0080,
0x0808,
0x0888,
0x2222,
0x4924,
0x4a52,
0x54aa,
0x5555,
0xd555,
0xd5d5,
0xddd5,
0xdddd,
0xdfdd,
0xdfdf,
0xffdf,
};
static void serial_setbrg_dev(const int dev_index)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
u32 uclk = get_uart_clk(dev_index);
u32 baudrate = gd->baudrate;
u32 val;
#if defined(CONFIG_SILENT_CONSOLE) && \
defined(CONFIG_OF_CONTROL) && \
!defined(CONFIG_SPL_BUILD)
if (fdtdec_get_config_int(gd->fdt_blob, "silent_console", 0))
gd->flags |= GD_FLG_SILENT;
#endif
if (!config.enabled)
return;
val = uclk / baudrate;
writel(val / 16 - 1, &uart->ubrdiv);
if (s5p_uart_divslot())
writew(udivslot[val % 16], &uart->rest.slot);
else
writeb(val % 16, &uart->rest.value);
}
/*
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
*/
static int serial_init_dev(const int dev_index)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
/* enable FIFOs, auto clear Rx FIFO */
writel(0x3, &uart->ufcon);
writel(0, &uart->umcon);
/* 8N1 */
writel(0x3, &uart->ulcon);
/* No interrupts, no DMA, pure polling */
writel(0x245, &uart->ucon);
serial_setbrg_dev(dev_index);
return 0;
}
static int serial_err_check(const int dev_index, int op)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
unsigned int mask;
/*
* UERSTAT
* Break Detect [3]
* Frame Err [2] : receive operation
* Parity Err [1] : receive operation
* Overrun Err [0] : receive operation
*/
if (op)
mask = 0x8;
else
mask = 0xf;
return readl(&uart->uerstat) & mask;
}
/*
* Read a single byte from the serial port. Returns 1 on success, 0
* otherwise. When the function is succesfull, the character read is
* written into its argument c.
*/
static int serial_getc_dev(const int dev_index)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
if (!config.enabled)
return 0;
/* wait for character to arrive */
while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK |
RX_FIFO_FULL_MASK))) {
if (serial_err_check(dev_index, 0))
return 0;
}
return (int)(readb(&uart->urxh) & 0xff);
}
/*
* Output a single byte to the serial port.
*/
static void serial_putc_dev(const char c, const int dev_index)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
if (!config.enabled)
return;
/* wait for room in the tx FIFO */
while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {
if (serial_err_check(dev_index, 1))
return;
}
writeb(c, &uart->utxh);
/* If \n, also do \r */
if (c == '\n')
serial_putc('\r');
}
/*
* Test whether a character is in the RX buffer
*/
static int serial_tstc_dev(const int dev_index)
{
struct s5p_uart *const uart = s5p_get_base_uart(dev_index);
if (!config.enabled)
return 0;
return (int)(readl(&uart->utrstat) & 0x1);
}
static void serial_puts_dev(const char *s, const int dev_index)
{
while (*s)
serial_putc_dev(*s++, dev_index);
}
/* Multi serial device functions */
#define DECLARE_S5P_SERIAL_FUNCTIONS(port) \
static int s5p_serial##port##_init(void) { return serial_init_dev(port); } \
static void s5p_serial##port##_setbrg(void) { serial_setbrg_dev(port); } \
static int s5p_serial##port##_getc(void) { return serial_getc_dev(port); } \
static int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \
static void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \
static void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); }
#define INIT_S5P_SERIAL_STRUCTURE(port, __name) { \
.name = __name, \
.start = s5p_serial##port##_init, \
.stop = NULL, \
.setbrg = s5p_serial##port##_setbrg, \
.getc = s5p_serial##port##_getc, \
.tstc = s5p_serial##port##_tstc, \
.putc = s5p_serial##port##_putc, \
.puts = s5p_serial##port##_puts, \
}
DECLARE_S5P_SERIAL_FUNCTIONS(0);
struct serial_device s5p_serial0_device =
INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0");
DECLARE_S5P_SERIAL_FUNCTIONS(1);
struct serial_device s5p_serial1_device =
INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1");
DECLARE_S5P_SERIAL_FUNCTIONS(2);
struct serial_device s5p_serial2_device =
INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2");
DECLARE_S5P_SERIAL_FUNCTIONS(3);
struct serial_device s5p_serial3_device =
INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3");
#ifdef CONFIG_OF_CONTROL
int fdtdec_decode_console(int *index, struct fdt_serial *uart)
{
const void *blob = gd->fdt_blob;
int node;
node = fdt_path_offset(blob, "console");
if (node < 0)
return node;
uart->base_addr = fdtdec_get_addr(blob, node, "reg");
if (uart->base_addr == FDT_ADDR_T_NONE)
return -FDT_ERR_NOTFOUND;
uart->port_id = fdtdec_get_int(blob, node, "id", -1);
uart->enabled = fdtdec_get_is_enabled(blob, node);
return 0;
}
#endif
__weak struct serial_device *default_serial_console(void)
{
#ifdef CONFIG_OF_CONTROL
int index = 0;
if ((!config.base_addr) && (fdtdec_decode_console(&index, &config))) {
debug("Cannot decode default console node\n");
return NULL;
}
switch (config.port_id) {
case 0:
return &s5p_serial0_device;
case 1:
return &s5p_serial1_device;
case 2:
return &s5p_serial2_device;
case 3:
return &s5p_serial3_device;
default:
debug("Unknown config.port_id: %d", config.port_id);
break;
}
return NULL;
#else
config.enabled = 1;
#if defined(CONFIG_SERIAL0)
return &s5p_serial0_device;
#elif defined(CONFIG_SERIAL1)
return &s5p_serial1_device;
#elif defined(CONFIG_SERIAL2)
return &s5p_serial2_device;
#elif defined(CONFIG_SERIAL3)
return &s5p_serial3_device;
#else
#error "CONFIG_SERIAL? missing."
#endif
#endif
}
void s5p_serial_initialize(void)
{
serial_register(&s5p_serial0_device);
serial_register(&s5p_serial1_device);
serial_register(&s5p_serial2_device);
serial_register(&s5p_serial3_device);
}
c)配置串口时钟
vim arch/arm/mach-s5pv210/clock.c
/* s5pv210: return PCLKs frequency */
static unsigned long get_pclk_sys(int dom)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long pclk;
unsigned int div;
unsigned int offset;
unsigned int pclk_sys_ratio;
div = readl(&clk->div0);
/*
* PCLK_MSYS_RATIO: [14:12]
* PCLK_DSYS_RATIO: [22:20]
* PCLK_PSYS_RATIO: [30:28]
*/
offset = 12 + (dom << 0x3);
pclk_sys_ratio = (div >> offset) & 0x7; /* modied by Sourcelink */
pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
return pclk;
}
/* s5pv210: return peripheral clock frequency */
static unsigned long s5pv210_get_pclk(void)
{
/* modied by SOurcelink */
return get_pclk_sys(CLK_P);
}
/* s5pv210: return uart clock frequency */
static unsigned long s5pv210_get_uart_clk(int dev_index)
{
/* modied by SOurcelink */
return s5pv210_get_pclk();
}
在上一篇文章分析过u-boot.bin初始化 可以自定义指示灯指示boot启动是否正常
#if ! defined(CONFIG_SPL_BUILD)
bl coloured_LED_init
bl red_led_on
#endif
vim common/board_f.c
__weak void coloured_LED_init(void) { *(volatile unsigned long*)0xE0200060 = 0x00011000;} /* modied by Sourcelink */
__weak void red_led_on(void) {*(volatile unsigned long*)0xE0200064 = 0x00000018;}
vim lib/display_options.c
int display_options (void)
{
#if defined(BUILD_TAG)
printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG);
#else
printf ("\n\n%s\n\n", version_string);
#endif
puts("Name : Sourcelink\n"); /* add by Sourcelink */
puts("Email: [email protected]\n");
return 0;
}
vim arch/arm/cpu/armv7/s5p-common/cpu_info.c
#ifdef CONFIG_DISPLAY_CPUINFO
int print_cpuinfo(void)
{
char buf[32];
const char *cpu_model;
int len;
/* For SoC with no real CPU ID in naming convention. */
cpu_model = fdt_getprop(gd->fdt_blob, 0, "cpu-model", &len);
/* modied by Sourcelink */
printf("CPU : %sV210@%sMHz \n", s5p_get_cpu_name(), strmhz(buf, get_arm_clk()));
return 0;
}
#endif
vim arch/arm/mach-s5pv210/clock.c
/*
* Copyright (C) 2009 Samsung Electronics
* Minkyu Kang <[email protected]>
* Heungjun Kim <[email protected]>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/clk.h>
#define CLK_M 0
#define CLK_D 1
#define CLK_P 2
/* modied by Sourcelink */
#ifndef CONFIG_SYS_CLK_FREQ_V210
#define CONFIG_SYS_CLK_FREQ_V210 12000000
#endif
/* s5pv210: return pll clock frequency (modied by Sourcelink) */
static unsigned long s5pv210_get_pll_clk(int pllreg)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long r, m, p, s, mask, fout;
unsigned int freq;
switch (pllreg) {
case APLL:
r = readl(&clk->apll_con0);
break;
case MPLL:
r = readl(&clk->mpll_con);
break;
case EPLL:
r = readl(&clk->epll_con0);
break;
case VPLL:
r = readl(&clk->vpll_con);
break;
default:
printf("Unsupported PLL (%d)\n", pllreg);
return 0;
}
/*
* APLL_CON: MIDV [25:16]
* MPLL_CON: MIDV [25:16]
* EPLL_CON: MIDV [24:16]
* VPLL_CON: MIDV [24:16]
*/
if (pllreg == APLL || pllreg == MPLL)
mask = 0x3ff;
else
mask = 0x1ff;
m = (r >> 16) & mask;
/* PDIV [13:8] */
p = (r >> 8) & 0x3f;
/* SDIV [2:0] */
s = r & 0x7;
freq = CONFIG_SYS_CLK_FREQ_V210;
if (pllreg == APLL) {
if (s < 1)
s = 1;
/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
fout = m * (freq / (p * (1 << (s - 1))));
} else
/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
fout = m * (freq / (p * (1 << s)));
return fout;
}
/* s5pv210: return ARM clock frequency (modied by Sourcelink) */
static unsigned long s5pv210_get_arm_clk(void)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long div;
unsigned long dout_apll, armclk;
unsigned int apll_ratio;
div = readl(&clk->div0);
/* ARM_RATIO: [2:0] */
apll_ratio = div & 0x7;
dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
armclk = dout_apll;
return armclk;
}
/* s5pv210: return HCLKD0 frequency */
static unsigned long get_hclk(void)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long hclkd0;
uint div, d0_bus_ratio;
div = readl(&clk->div0);
/* D0_BUS_RATIO: [10:8] */
d0_bus_ratio = (div >> 8) & 0x7;
hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
return hclkd0;
}
/* s5pv210: return HCLKs frequency */
static unsigned long get_hclk_sys(int dom)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long hclk;
unsigned int div;
unsigned int offset;
unsigned int hclk_sys_ratio;
if (dom == CLK_M)
return get_hclk();
div = readl(&clk->div0);
/*
* HCLK_MSYS_RATIO: [10:8]
* HCLK_DSYS_RATIO: [19:16]
* HCLK_PSYS_RATIO: [27:24]
*/
offset = 8 + (dom << 0x3);
hclk_sys_ratio = (div >> offset) & 0xf;
hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);
return hclk;
}
/* s5pv210: return PCLKs frequency */
static unsigned long get_pclk_sys(int dom)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long pclk;
unsigned int div;
unsigned int offset;
unsigned int pclk_sys_ratio;
div = readl(&clk->div0);
/*
* PCLK_MSYS_RATIO: [14:12]
* PCLK_DSYS_RATIO: [22:20]
* PCLK_PSYS_RATIO: [30:28]
*/
offset = 12 + (dom << 0x3);
pclk_sys_ratio = (div >> offset) & 0x7; /* moied by Sourcelink */
pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
return pclk;
}
/* s5pv210: return peripheral clock frequency */
static unsigned long s5pv210_get_pclk(void)
{
/* modied by SOurcelink */
return get_pclk_sys(CLK_P);
}
/* s5pv210: return uart clock frequency */
static unsigned long s5pv210_get_uart_clk(int dev_index)
{
/* modied by SOurcelink */
return s5pv210_get_pclk();
}
/* s5pv21: return pwm clock frequency */
static unsigned long s5pv210_get_pwm_clk(void)
{
/* modied by Sourcelink */
return s5pv210_get_pclk();
}
unsigned long get_pll_clk(int pllreg)
{
/* modied by Sourcelink */
return s5pv210_get_pll_clk(pllreg);
}
unsigned long get_arm_clk(void)
{
/* modied by Sourcelink */
return s5pv210_get_arm_clk();
}
unsigned long get_pwm_clk(void)
{
/* modied by Sourcelink */
return s5pv210_get_pwm_clk();
}
unsigned long get_uart_clk(int dev_index)
{
/* modied by Sourcelink */
return s5pv210_get_uart_clk(dev_index);
}
void set_mmc_clk(int dev_index, unsigned int div)
{
/* Do NOTHING */
}
6、更改sd复制的扇区大小
vim board/samsung/smdkv210/smdkv210.c
CopySDMMCtoMem(ch, 32, 800, (unsigned int *)CONFIG_SYS_SDRAM_BASE, 0);
在完成前面那么多步骤后把u-boot.bin下载到第32扇区,smdkv210-spl.bin下载到第一扇区发现程序死在了NAND: 搜索NAND:后发现 ,是死了在onenand初始化故暂时屏蔽它。
vim common/board_r.c
#ifdef CONFIG_CMD_ONENAND
//initr_onenand, /* modied by Sourcelink */
#endif
文章浏览阅读1.6k次。原因:由于网络原因没有将Maven的依赖下载完整解决:1、切换到maven的本地仓库2、在当前目录打开cmd命令行3、执行命令 :for /r %i in (*.lastUpdated) do del %i..._maven .lastupdate
文章浏览阅读5.8k次,点赞8次,收藏30次。本文是 Open XML SDK 的入门文章,将逐步讲解如何生成一个下面这样的 Word 文档:有关 Open XML SDK 的详细内容,请参阅这个链接:欢迎使用 Open XML SDK 2.5 for Office创建示例程序..._c#openxml操作word
文章浏览阅读9.5k次,点赞10次,收藏80次。[原文链接](http://xilinx.eetrend.com/article/8871) 由 技术编辑archive1 于 星期三, 07/22/2015 - 15:42 发表 现在的FP..._system generator
文章浏览阅读929次,点赞14次,收藏17次。查询一个一定不存在的数据,由于缓存必定不命中,而去查询数据库,查数据什么也查不到而且我们也没有把这个空结果写入缓存,导致每次差这个数据都会访问一遍数据库,使缓存失去效果,容易被人利用导致数据库压力大,最终导致系统崩溃
文章浏览阅读862次。一、JSP技术1.jsp脚本和注释jsp脚本:1) ----- 内部的java代码翻译到service方法的内部2) ----- 会被翻译成service方法内部out.print()3) ---- 会被翻译成servlet的成员的内容 jsp注释: 不同的注释可见范围是不同1)Html注释: ---可见范围 jsp源码、翻译后的servlet、页面 显示ht_javaweb利用el和jstl在jsp页面中打印所有的水仙花数。
文章浏览阅读1.2k次。Spice Server中USBREDIR Channel初始化首先,USBREDIR在QEMU中是一个虚拟设备而存在的。QEMU启动时将初始化该设备,为建立USB Redirect Channel做准备。其模块定义于:hw/usb/redirect.c:static const TypeInfo usbredir_dev_info = { .name = TYPE_USB_REDIR, .parent = TYPE_USB_DEVICE, ._usbredir
文章浏览阅读2.7w次,点赞5次,收藏58次。无论是在办公还是在生活中,流程图都是一个必不可少的重要辅助工具,大到建筑设计小到生活计划都需要使用流程图来帮助我们更好的完成每一件事情!但是流程图怎么做呢?很多朋友还是不知道的,今天小编给大家带来快速绘制流程图的教程! 其实流程图的绘制没有想象中那么复杂和困难,只要选对专业的流程图制作软件,几分钟便可以画好一张流程图!工具:迅捷画图准备好画图工具之后不要急着操作,首先我们需..._类的流程图怎么画
文章浏览阅读6k次,点赞2次,收藏5次。近来比较繁忙,所以博客近期一直没有更新,今天就来和大家说说关于elementUI dialog弹窗清空值的问题在vue + elementUI项目中有时候会大量的用到弹窗这个组件,所以就对这个组件进行了统一封装。但是对于弹窗中的值的清空问题就有些麻烦了。当dialog 中嵌套的是form表单时,我们可以使用Element UI自带的清空form表单方法this.$refs.formData.resetFields(); //重置表单数据,清除校验信息或者手动的去重置清空表单数据this._eldialog打开清除数据v-if
文章浏览阅读456次。docker容器自动启动设置docker容器自动启动设置第一种方法docker ps -a然后使用命令对容器进行重启docker restart imageid这样就可以将容器设置为开机启动了第二种方法在运行docker容器时可以加如下参数来保证每次docker服务重启后容器也自动重启:docker run --restart=always如果已经启动了则可以使用如下命令:docker update --restart=always ...
文章浏览阅读298次。组件守卫vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。全局前置守卫beforeEach当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。你可以使用 router.beforeEach 注册一个全局前置守卫://模拟登录状态let loginStatus = falseconst router = [ { _vue组件守卫 作用
文章浏览阅读289次。《Linux》天影linux系列笔记一——linux常用命令详解:cd
文章浏览阅读1k次,点赞17次,收藏26次。领域专用语言Elasticsearch提供了基于JSON的DSL来定义查询。DSL由叶子查询子句和复合查询子句两种子句组成。_elasticsearch中涉及到的设计