Daily report on the work of July 7

2024-02-04 22:18
文章标签 work report daily july

本文主要是介绍Daily report on the work of July 7,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

         今天是7月8日.最近处理realtek 2692 的待机开机死机重启等问题,是我们做的创维的方案遇到的最棘手的问题,如今E82项目已经到了最后关头,必须在短期内快速找出各个问题的原因.终于到了7月7日所有问题都有了结论,现总结于此.

 问题一共有三种:

1.快速按power键,在开机的过程中有show logo之后LED为暗,led灯为绿,并待机待不下去.uart为关.

    这个问题只有在uart有关的情况下才能测出.开始一直怀疑是开机过程沒开起来,后来跟踪了整个开机过程,因为要关掉打印才能测出问题,所以只有通过强制打印,来测试程序到底在什么地方卡住了,没有继续跑下去,因为这个问题应该是某个线程卡住了,

也造成watchdog没有重启.

 强制打印的方式为:

 static void uart_Write(char c)
{

        while (1) {

                if      (rtd_inl(UART_UART2_DLL_VADDR + UART_LSR) & 0x60)
                        break;
        }

        rtd_outl(UART_UART2_DLL_VADDR +UART_THR, c);
        if (c == 0x0a)
                rtd_outl(UART_UART2_DLL_VADDR +UART_THR, 0x0d);
}

在asmlinkage void __init start_kernel(void){

}

中强迫打印,看卡住的地方是否已经跑进了kernel.

但是每次强迫打印都是跑完了的.

后来因为chuck的帮助,说明问题可能是发生在AP,那么我们采用了设定GPIO的方式来验证.

找到一个空闲的pin35来做GPIO拉高拉低来判断是否在AP卡住.

在board_customer_at_tv010_ko5.c

GPIO_Set(PIN_USB_PWR_FLAG1, SG_PANEL_3D_OFF);

#define PIN_USB_PWR_FLAG1        PIN(GPIO_GROUP_R, GPIO_PIN3, GPIO_TYPE_INPUT, GPIO_INTERRUPT_TYPE_NONE, GPIO_INIT_TYPE_1)

设定pin35为GPIO,并为输入并拉低.

在poweron中收到powerkey时,

case MSG_RC_POWER:

IoReg_Mask32(0xb8012040, ~(1<<27), 1<<27);
IoReg_Mask32(0xb8012044, ~(1<<19), 1<<19);
收到key后将gpio拉高

并时时示波器测量波形,最后发现当问题出现时,GPIO确实有被拉高.

证明问题是发生在AP卡住.

但因为如果打开打印却很难测出问题.

所以后来去质量部用了24台机器来做实验,在打开uart的情况下抓打印.

最后终于抓到打印并发现问题是卡住播放待机音乐里面.

因为播放待机是采用avcbplaymedia来播放的,是采用了多媒体的播放通道.

在设定播放通道之前并没有去释放开机时所进入的TV,AV...等通道

那么卡住的地方就很可能是在同时识别和播放两个通道的东西而卡住.最后我提出的是

在识别完信号nosignal,ready的时候才去做待机

再后来还是能测到问题,所以我提出了

在播放待机音乐之前加上SrSource_Deactivate(RT_VOUT_MAIN,TRUE);去释放当前通道和播放的media.

最后在关闭打印的 情况下12台机器测试1.5hours并没有发现问题,说明问题已解.

第二个问题是:

按在关闭uart的情况下去不断DC待机开机,在开机的时候,有现实开机log以及播放开机音乐后不久又重新进入待机

后者重启.这个问题只出现在两台机器上,所以可能与平台 有关.

关于这个问题也提到了要关闭uart才能测到,所以也是问题棘手的地方,因为我们很难知道问题到底发生在什么位置出了问题.

后来我想到一个办法,就是验证 打印是否起到的是 delay的作用.

我在kernel中的printk.c中所有调用printk函数的地方都加了delay,delay了10ms或者50ms都发现,在两台很容易出现问题的机器上测试了半个小时都无发现问题

原本这些机器一般在1-2分钟就会有问题.

因此发现了家delay可以起到效果.

我便进一步猜测,如果delay有用,那么delay所得到的作用,假设只是一部分code需要做delay.

那么我只要找到那部分code需要delay就可以大概知道问题出现在什么位置

想到用调用printk次数的方式来锁定问题大约出现的位置.

我将全部打印都打开,并在每次调用printk的地方都return 0.这样问题也可以很快被测出来.

因此,我让在调用了前90次printk有打印出來,后面的没有.问题也很快出來.

在调用150次printk有打印出来,后面的没有.问题有发现.

最后发现调用150次附近去关闭打印会有问题.

我在采用调用前150次的printk的时候直接return 0,发现还有问题

在调用前140次直接return 0时,发现未测到问题

最后在140次到160次直接有打印的话,测不到问题.

因为我在调用printk150次之后把打印打开,这样我们既锁定问题出现的位置并能看到打印.

这样我们也可以加我们想要的测试代码.

发现每次重启或者自动待机都发生在kernel跑完,AP才要出來的地方.

发现每次出现问题都是在打印完
init started:  BusyBox v1.1.3 (2011.01.12-08:18+0000) multi-call binary
Starting pid 109, console /dev/ttyS0: '/bin/sh'
BusyBox v1.1.3 (2011.01.12-08:18+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
.....err
 
上述之后有打印err之后重启的.而如果能正常开机的都很少有这种情况发生.
 
err主要有两种:
error:RX FIFO overflow , status = 0x10 
error:RX FIFO overflow , status = 0x50 
error:RX FIFO overflow , status = 0x50 
... ...
error:RX FIFO overflow , status = 0x51 
error:RX FIFO overflow , status = 0x50 
error:RX FIFO overflow , status = 0x50 
 
或者
 
error:RX desc. unavailable ,status = 0x60 
 error:RX desc. unavailable ,status = 0x20 
 error:RX desc. unavailable ,status = 0x20 
... ...
 error:RX desc. unavailable ,status = 0x21 
 error:RX desc. unavailable ,status = 0x21 
 error:RX desc. unavailable ,status = 0x21
但是,这部分打印是在网络中断里面打印的,但是他们并不认为这部分有问题.但是我在测试的时候确实有发现

但这部分打印比较多的时候机器一定会重启.


最后还是采用检测判断watchdog是否又被触发,并找出触发者是谁. 有三个嫌疑人:AP,KERNEL,ROS

在wdg_user.h中加入了,写ddr的code来记录触发者.

发生是在kernel起来时,ros起来时,加入初始化某个ddr的地址的值.

然后在watchdog重启后去记录 usr到这个地址.

这样我们可以知道是哪里出了问题.

static inline void  wdg_core_initializor(void)
{
    struct _wdg_user_area *w = REFER_TO_WDG();
    struct _wdg_user_area *p = REFER_TO_WDG_PRIVATE();

    while (!rtd_inl(HD_SEM_reg));
    
    if (WDG_READY(w) && WDG_READY(p)) {
        // Chuck: the setting is old, need a re-init
        if ((w->threshold[WDG_ROS_ISR] != 0) && (w->threshold[WDG_KERNEL] != 0))
            w->ready_magic = ~WDG_READY_MAGIC;
    }

    if ((w->ready_magic != swap(WDG_READY_MAGIC)) || (p->ready_magic != swap(WDG_READY_MAGIC))) {
        struct _wdg_user_area proto = WDG_USER_AREA_PROTOTYPE;

        *p = *w = proto;
        rtd_outl(0xaff00000, 0x2379);
                    rtd_outl(0xaff00004, 0x2379);
                    rtd_outl(0xaff00008, 0x2379);
                    rtd_outl(0xaff0000c, 0x2379);
                    rtd_outl(0xaff00010, 0x2379);
        WDG_MSG("Watch dog's core initializor\n");
    }

    WDG_TIMER_START();
    rtd_outl(HD_SEM_reg, 0);
}

在wdg_core_initializor(){

//加入

       rtd_outl(0xaff00000, 0x2379);//0x8ff00000 是0xaff0000的cache.

                    rtd_outl(0xaff00004, 0x2379);
                    rtd_outl(0xaff00008, 0x2379);
                    rtd_outl(0xaff0000c, 0x2379);
                    rtd_outl(0xaff00010, 0x2379);

}

并在

static __inline void wdg_core_handler(void)
{
    struct _wdg_user_area *w = REFER_TO_WDG();
    struct _wdg_user_area *p = REFER_TO_WDG_PRIVATE();
    int user;

    if (!WDG_READY(w) || !WDG_READY(p))
        return;

    for (user=0; user<w->num; user++) {
        if (w->count[user] != p->count[user]) {
            p->fail[user] = 0;
            p->count[user] = w->count[user];
        }
        else {
            if (w->count[user] != 0) {
                if (p->fail[user]++ > p->threshold[user]) {
                    WDG_FALL_SLEEP(p);
        //            WDG_MSG("WDT_MR is %x\n", psStatus);
                    rtd_outl(0xaff00000, user);
                    rtd_outl(0xaff00004, w->count[user]);
                    rtd_outl(0xaff00008, p->count[user]);
                    rtd_outl(0xaff0000c, p->threshold[user]);
                    rtd_outl(0xaff00010, p->fail[user]);
                    WDG_MSG("wdg_user(%x) fail to clear count (%x %x)  threshold(%x) fail:%x \n",
                        user, w->count[user], p->count[user], p->threshold[user], p->fail[user] );
                }
            }
        }
    }

    if (WDG_IS_BARKING(p)) {
        WDG_TIMER_RELOAD();
    }

    return;
}

加入记录user.

在time.c中

timer_interrupt();会沒隔10ms会进来一次去判断调用watchdog去检测是AP,ROS或者kernel是否有回馈,如果无回馈则说明挂掉了那么会在这里记录user.

#ifdef CONFIG_REALTEK_WDT
    // Kick the HW watchdog
    if (!gWatchdogStop){
    rtd_outl( 0xb8011320, 0x36);    
    wdg_core_handler();
    }
#endif

如:irqreturn_t __imem timer_interrupt(int irq, void *dev_id)
{
    unsigned int status;    
#ifdef CONFIG_REALTEK_WDT
    extern unsigned char gWatchdogStop;
#endif
    write_seqlock(&xtime_lock);

    rlx_timer_ack();

    /*
     * call the generic timer interrupt handling
     */
    do_timer(1);

    /*
     * If we have an externally synchronized Linux clock, then update
     * CMOS clock accordingly every ~11 minutes. rtc_rlx_set_time() has to be
     * called as close as possible to 500 ms before the new second starts.
     */
    if (ntp_synced() &&
        xtime.tv_sec > last_rtc_update + 660 &&
        (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
        (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
        if (rtc_rlx_set_mmss(xtime.tv_sec) == 0) {
            last_rtc_update = xtime.tv_sec;
        } else {
            /* do it again in 60 s */
            last_rtc_update = xtime.tv_sec - 600;
        }
    }

    write_sequnlock(&xtime_lock);

    /*
     * In UP mode, we call local_timer_interrupt() to do profiling
     * and process accouting.
     */
    local_timer_interrupt(irq, dev_id);

#ifdef CONFIG_REALTEK_WDT
    // Kick the HW watchdog
    if (!gWatchdogStop){
    rtd_outl( 0xb8011320, 0x36);    
    wdg_core_handler();
    }
#endif

    // clear timer's pending bit
    status = rtd_inl(TC_TMR4_VR_VADDR);
    //we should ack timer4 only!
    status &= 0xfffffffe;
    status |= TC0IP;
    rtd_outl(TC_TMR4_VR_VADDR, status);

    return IRQ_HANDLED;
}

贴上我实验后的回信:

将watdog,中写0x8ff00000 都改为0xaff00000,重编了av_core.img,vmlinux.bin,kernel.img,还有AP.
测到的结果还是一样的:
TC_WR_MR_VADDR 有加1.
TC_WR_MR_VADDR is  0x00010000
但是,0xAFF00000的值依然为2379
0xaff00000@1@=0x79230000
0xaff00004@1@=0x79230000
0xaff00008@1@=0x79230000
0xaff0000c@1@=0x79230000
0xaff00010@1@=0x79230000
 
所以要思考一下是否watdog有被触发,但是却没有跑到rtd_outl(0xaff00000, user); 中去记录user?
log见附件,(打印还包含发生自动重启后的打印,请看最后一次打印)
 
另外,我故意kill掉AP的时候,0xaff00000的值是正确的.
0xaff00000@1@=0x2
0xaff00004@1@=0x6
0xaff00008@1@=0x6
0xaff0000c@1@=0x3e8
0xaff00010@1@=0x3ea
 
所以要想办法找到触发watdog的user是谁?

这表面这次watchdog 虽然有触发但是不是timer去触发的,而是timer被卡死,而时间一到也会去触发.

因为没有人去call wdg_core_handler

原理的机制是定期去检测linux/ros/ap是否能正常运作.

但今天这个检测的人反而出了问题.

所以时间一到还是会去reset.

linux/ros/ap会定期跟timer説,若有一个人没有定期回报給timer,也会reset.

当然如果linux/ros/ap都正常,但是timer挂掉,还是会reset.

因此才不会在0xaff0000去记录.


还有第二个发现就是:

之前不是提到有eth的err报出來吗?

但是如果把网线拔掉,就不应该会报错,如果还报错则可以说明eth的芯片有问题!!!


因此我们在config中将eth拿掉

在realtek config 中的nfs function support 关掉.

并Device Drivers --->realtek related drivers--->RTL 8139CP+ nic support 关掉.

拿掉了eth后测试了2个小时沒发现问题.

并且会印出

SIOCGIFFLAGS: No such device(因为AP去尝试去开eth).

说明eth的模块有问题.


在8139cplus.c中做了如下实验:

1.在cp_interrupt()函数中

    if (!status || (status == 0xFFFF))
        return IRQ_NONE;

之后直接

return IRQ_HANDLED;

这样的话会造成,开机后不断重启.

烧到正常的板子也会.

2.hw reset:

将cp_rx_poll的cpr16(ISR) & (RX_FIFOOVR )改为:if (cpr16(ISR) & (RX_FIFOOVR | RX_EMPTY))


3.换IRQ

把timer和eth的IRQ互换.

drivers/net/8139cplus.h

#define RTD2885_LAN_IRQ_NUM (10) 改成 3

linux-2.6.23\arch\rlx\bsp\timer.c的

bsp_timer_setup();函数中

setup_irq(3, irq);改为setup_irq(10, irq);

    rtd_outl(BUS_SIC_M_GIR5_VADDR, (rtd_inl(BUS_SIC_M_GIR5_VADDR) & ~(0x0f<<TCIE4IRS_OFFSET)) | (0x3 << TCIE4IRS_OFFSET));

改为:

 rtd_outl(BUS_SIC_M_GIR5_VADDR, (rtd_inl(BUS_SIC_M_GIR5_VADDR) & ~(0x0f<<TCIE4IRS_OFFSET)) | (0xa << TCIE4IRS_OFFSET));

测试结果是还没有效果.

4.在cp_init_one()函数中将

    /* Open NIC's clock gating. */
    rtd_outl(SC_CLKEN2,rtd_inl(SC_CLKEN2) | ETH_CLKEN);
    //rtd_outl(SC_PHY_CLKEN,rtd_inl(SC_PHY_CLKEN) | MII_PHY_CLKEN);
    udelay(100);
    rtd_outl(SC_PLLETN0,(rtd_inl(SC_PLLETN0)&(~PLLETN_PWDN)));
    udelay(100);
    rtd_outl(SC_PLLETN0,(rtd_inl(SC_PLLETN0)&(~PLLETN_OEB)));
    udelay(100);
    rtd_outl(SC_PLLETN0,(rtd_inl(SC_PLLETN0)|PLLETN_RSTB));

改为:

    /* Open NIC's clock gating. */
    rtd_outl(SC_CLKEN2,rtd_inl(SC_CLKEN2) | ETH_CLKEN);
    //rtd_outl(SC_PHY_CLKEN,rtd_inl(SC_PHY_CLKEN) | MII_PHY_CLKEN);
    //udelay(100);
    udelay(100*1000);
    rtd_outl(SC_PLLETN0,(rtd_inl(SC_PLLETN0)&(~PLLETN_PWDN)));
    udelay(100*1000);
    rtd_outl(SC_PLLETN0,(rtd_inl(SC_PLLETN0)&(~PLLETN_OEB)));
    udelay(100*1000);
    rtd_outl(SC_PLLETN0,(rtd_inl(SC_PLLETN0)|PLLETN_RSTB));

之后,在测试发现不会卡住timer了

但是还是会重启,重启后有记录卡住的user为:

0xaff00000@2@=0x0 0xaff00004@2@=0x3 0xaff00008@2@=0x3 0xaff0000c@2@=0xc8 0xaff00010@2@=0xca 

0x0代表卡住user的人是ros.(ap是2)


但是加delay是不正确的,clock and pll ready的时间是可以计算出來的.

所以我这款IC比一般的ic要长,而ros卡住也可能会是因为这个原因以前,

所以目前采用的方法是把其中一块板子#36送RMA分析.


而另一块板子的IC在创维手工换IC换了一个小时后,拿来做测试发现,测试一个小时都无发现.

证明这个bug是IC引起的.而且应该是IC内的ethernet有问题.

因为如果不开网路 不应该有网路中断,也不会有Rx desc error.


第三种问题则是开机或者待机时开机,led变黄,但屏黑,无打印,遥控无效.

这个问题也出现在#36的机器上也只有这台机器有问题并且这台是IC有问题的机器.









 

这篇关于Daily report on the work of July 7的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/678951

相关文章

2015多校联合训练第三场Work(hdu5326)

题意: a是b的上司,b是c的上司,则a是c的上司,问构成一个树种,有多人是 k个人的上司 思路: 先找出root,然后dfs一下就行 #include <bits/stdc++.h>#define LL long longusing namespace std;const int MAXN = 1e6;int f[105];int n, k;int mp[101][101];

The Prompt Report 2

The Prompt Report 提示工程调查报告《The Prompt Report: A Systematic Survey of Prompting Techniques》 主要内容 Core Prompting Techniques Text based Techniques:PRISMA流程,58中基于文本的提示技术,提示语术语分类表;MLT:Multilingual T

[LeetCode] 739. Daily Temperatures

题:https://leetcode.com/problems/daily-temperatures/description/ 题目 Given a list of daily temperatures T, return a list such that, for each day in the input, tells you how many days you would have to

HOW DO VISION TRANSFORMERS WORK

HOW DO VISION TRANSFORMERS WORK Namuk Park1,2, Songkuk Kim1 1Yonsei University, 2NAVER AI Lab{namuk.park,songkuk}@yonsei.ac.kr 总结 MSA 改善模型泛化能力: MSA 不仅提高了模型的准确性,还通过平滑损失景观来提高泛化能力。损失景观的平坦化使得模型更容易优化,表现

work note

1:  sum_total 是什么意思?  没有百度出来 见proce:  rptMohthCdr

调用ASH Report

--调用ASH Report --?/rdbms/admin/ashrpt.sql SYS@PROD1> start ?/rdbms/admin/ashrpt.sqlCurrent Instance~~~~~~~~~~~~~~~~DB Id DB Name Inst Num Instance----------- ------------ -------- -----

【RabbitMQ】work模式

上一篇博客的作为rabbitMQ的入门程序,也是简单队列模式,一个生产者,一个消费者,今天这篇博客介绍work模式,一个生产者,多个消费者,下面的例子模拟两个消费者的情况。 图示:            一个生产者、两个消费者;一个消息只能被一个消费者获取。   在work模式中可以分为两种模式,一种是两个消费者平均消费队列中的消息,即使他们的消费能力是不一样的,

innovus:report_area和reportGateCount报告module面积的差异

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 相关文章链接:

帆软Report 时间日期相关公式

公式 时间日期相关公式 时间日期相关公式 获取当月的天数: DAYSOFMONTH(DATE($iYear,$iMonth,'01'))

学习大数据DAY44 帆软 report 配置

目录 Linux 系统独立部署 Tomcat 服务器设置 上机练习 Linux 系统独立部署 ## 题目要求 在 LINUX 系统, Tomcat 服务器容器下,完成 FineReport 报表工程的独立部 署,并设置服务器开机自启动,并请实操演示 得分点(完成得满分,未完成得 0 分): FineReport 报表工程的独立部署