1. 概述
UBOOT的代码有其特殊性,如果没有仿真器,难以方便的调试。一般用printf来调试很方便,可是难以将代码的各个逻辑都走到。就笔者个人的经验而言,BUG的出现往往是那些没有注意的逻辑流程出问题,所以代码写好后,每一行都过一遍十分重要。不要想当然的以为,“这个else的情况不可能出现”,或者自以为“这么简单的代码,一定没有问题”。防患于未然才是王道,等到项目快结束的时候,一个难以察觉的到的bug再找起来就很困难了。
2. UBOOT中所做的修改
UBOOT中所作的修改用patch的形式来展现,如下:
index 89c5483..74769bf 100644
--- a/booter/lib_arm/bootm.c
+++ b/booter/lib_arm/bootm.c
@@ -30,6 +30,7 @@
#include <bootimg.h>
#include "../yuwei/libra_app.h"
+#include "../libra/libra_impl.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -62,6 +63,31 @@ static struct tag *params;
static char bootargs_buffer[1024];
// 定义了一个enum类型
+typedef enum {
+ otg_null,
+ otg_device,
+ otg_host
+} otg_type_t;
+
// 获取当前otg的状态,是device还是host。
+static otg_type_t i_fetch_otg_device_mode(void) {
+ sram_status_t st;
+ int passport = PASSCODE;
+ long ret = lba_sram_status_fetch(&passport, &st);
+ if (ret != e_ok) {
+ printf("***lba_sram_status_fetch,ret = %ld***\n", ret);
+ return otg_null;
+ }
+ if ( (st.reserved[13] & (1<<4)) && !(st.reserved[14] & (1<<4)) ) {
+ return otg_device;
+ } else if ( !(st.reserved[13] & (1<<4)) && (st.reserved[14] & (1<<4)) ) {
+ return otg_host;
+ } else {
+ printf("st.reserved[13] = 0x%x, st.reserved[14] = 0x%x, is OK???\n",
+ st.reserved[13], st.reserved[14]);
+ return otg_null;
+ }
+}
+
int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
bd_t *bd = gd->bd;
@@ -108,6 +134,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
#endif
#ifdef CONFIG_CMDLINE_TAG
+ #if YW_BOARD_TYPE_T6
/*
* King add to check board type for recover. @ 2016.01.27
*/
@@ -123,9 +150,21 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
intonum = 0x12;
}
memset(bootargs_buffer, 0, sizeof(bootargs_buffer));
- sprintf(bootargs_buffer, "%s ywboardtype=%x",
- commandline, intonum);
+
// 上述接口的调用
+ otg_type_t otg_type;
+ char type_str[64];
+ memset(type_str, 0, sizeof(type_str));
+ if ( (otg_type = i_fetch_otg_device_mode()) == otg_host ) {
+ strcpy(type_str, "ywotgtype=otg_host");
+ printf("otg type = %s\n", type_str);
+ } else if (otg_type == otg_device) {
+ strcpy(type_str, "ywotgtype=otg_device");
+ printf("otg type = %s\n", type_str);
+ } // else do nothing...
+ sprintf(bootargs_buffer, "%s ywboardtype=%x %s",
+ commandline, intonum, type_str);
strcpy(commandline, bootargs_buffer);
+ #endif
代码说明:
修改的代码很简单。定义了一个enum类型,一个获取otg状态的函数,一个调用者。其中和平台相关的是lba_sram_status_fetch,其他东西都是通用的。
lba_sram_status_fetch这个函数的功能是获取平台的静态内存里面的数据,其中和这次修改相关的成员是reserved[13]和reserved[14]。
所以,只需要更改reserved[13]和reserved[14]的值,就可以把本次修改的代码逻辑走完。
3. C++万能模版的实现
testBaseClass.h
<pre name="code" class="html"><pre name="code" class="html">#ifndef __TESTBASECLASS__H
#define __TESTBASECLASS__H
#include <libio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
template <typename T>
class testBaseClass {
private:
bool status; //定义了一个状态,来判断代码运行过程中是否出错。
public:
testBaseClass(int arg = 0, T* val = NULL); // 构造函数,默认参数都是0。
~testBaseClass() {
}
virtual void run(void *)=0; // 一个纯虚函数,用作标准的接口。
bool getStatus(void) const {
return status;
}
};
template <typename T>
testBaseClass<T>::testBaseClass(int arg, T* val)
{
int getv;
for (int i=0; i<arg; i++) {
cout << "Enter a digit: "; // 输入数字的提示
cin >> getv; // 将输入的数字存入getv
if (val != NULL) {
val[i] = getv;
} else {
status = false;
return;
}
}
status = true;
}
#endif
otgTypeTest.cpp
#include "testBaseClass.h"
#include <string.h>
// 枚举类型照抄
typedef enum {
otg_null,
otg_device,
otg_host
} otg_type_t;
// 结构体照抄
typedef struct sram_sts {
int reserved[16];
} sram_status_t;
// 手动定义了一个全局变量
sram_status_t st;
// 获取otg状态的函数,平台相关的部分
static otg_type_t i_fetch_otg_device_mode(void) {
if ( (st.reserved[13] & (1<<4)) && !(st.reserved[14] & (1<<4)) ) {
return otg_device;
} else if ( !(st.reserved[13] & (1<<4)) && (st.reserved[14] & (1<<4)) ) {
return otg_host;
} else {
printf("st.reserved[13] = 0x%x, st.reserved[14] = 0x%x, is OK???\n",
st.reserved[13], st.reserved[14]);
return otg_null;
}
}
// 模版的类型是int,目前只实现了int版本,以后会扩充到其他的类型。
class otgTypeTest : public testBaseClass<int>
{
public:
otgTypeTest(int argc, int *p) : testBaseClass(argc, p)
{
}
void run(void *obj) { // run函数里面填的是当时UBOOT的调用,照抄。
otg_type_t otg_type;
char type_str[64];
memset(type_str, 0, sizeof(type_str));
if ( (otg_type = i_fetch_otg_device_mode()) == otg_host ) {
strcpy(type_str, "ywotgtype=otg_host");
printf("otg type = %s\n", type_str);
} else if (otg_type == otg_device) {
strcpy(type_str, "ywotgtype=otg_device");
printf("otg type = %s\n", type_str);
} // else do nothing...
}
};
int main(void)
{
otgTypeTest *test = new otgTypeTest(2, &st.reserved[13]); // reserverd[13],reserved[14]是用从外界输入的,来模拟。
if (test->getStatus())
test->run(NULL);
else
cout << "otgTypeTest obj construct error\n";
return 0;
}
<pre name="code" class="html">
<pre name="code" class="html">