您的位置:首页 > 编程语言 > C语言/C++

UBOOT代码调试万能模版-C++模版小试牛刀 王凯(光谷)

2016-02-25 16:13 344 查看

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; // 将输入的数字存入getvif (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);elsecout << "otgTypeTest obj construct error\n";return 0;}
<pre name="code" class="html"><pre name="code" class="html">
  
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: