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

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">


 
 


 
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值