天天看點

LED顯示(3):LED顯示子產品中的幾個錯誤

LED顯示(3):LED顯示子產品中的幾個錯誤

先貼程式了這樣友善說話

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

#define LED_OE 0x20

#define LED_AL 0x00

#define LED_AR 0x10

#define LED_AD 0x20

#define LEDCS 0x04

#define FLAG_OE 0x20350000

//#define FLAG_INER 0x2360000

#define FLAG_INER 0x20360000

#define FLAG_B 0x20380000

#define DATA_OUT 0x20390000

/**

*#define led_enable *(volatile int *)(FLAG_OE)

*#define data_write *(volatile int *)(FLAG_INER)

*#define disp_select *(volatile int *)(FLAG_B)

*#define data2disp *(volatile int *)(DATA_OUT)

*/

#define led_enable (*(volatile unsigned char *)(FLAG_OE))

#define data_write (*(volatile unsigned short *)(FLAG_INER))

#define disp_select (*(volatile unsigned short *)(FLAG_B))

#define data2disp (*(volatile unsigned short *)(DATA_OUT))

const unsigned int led_code[10] = {0x3f, 0x06, 0x5b, 0x4f, 0x66,

0x6d, 0x7d, 0x27, 0x7f, 0x6f};

static inline void udelay(volatile int us)

{

volatile int i;

while(us--)

for(i = 30; i > 0; i--);

}

static inline void mdelay(volatile int ms)

{

while(ms--)

{

udelay(700);

}

}

static inline void led_init(void)

{

led_enable = (0xff & (~LED_OE));

mdelay(500);

}

static inline void led_delete(void)

{

led_enable |= LED_OE;

}

static void led_display(unsigned char led_num, unsigned char data)

{

printk(KERN_INFO "led_num:%d data:%d/n", led_num, data);

switch(led_num)

{

case 1:

disp_select = LED_AL;

break;

case 2:

disp_select = LED_AR;

break;

case 3:

disp_select = LED_AD;

break;

default:

printk("ERROR!/n");

break;

}

data2disp = led_code[data];

data_write = 0x00; //與下面一行一起産生一個上升沿

data_write = LEDCS; //将資料寫入CPLD

}

static int __init sample_module_init(void)

{

//int a = (int)led_enable;

//printk("%d/n", a);

printk(KERN_INFO "init sample module device/n");

led_init();

led_display(1, 3);

mdelay(1000);

led_display(2, 2);

//a = (int)led_enable;

//printk("%d/n", a);

return 0;

}

static void __exit sample_module_cleanup(void)

{

//int a = (int)led_enable;

//printk("%d/n", a);

printk(KERN_INFO "cleanup sample module device/n");

led_display(3, 3);

mdelay(1000);

led_display(4, 4);

//led_delete();

//a = (int)led_enable;

//printk("%d/n", a);

}

module_init(sample_module_init);

module_exit(sample_module_cleanup);

MODULE_DESCRIPTION("sample module");

MODULE_LICENSE("GPL");

//問題整理:

//問題1:

//症狀:

// 塊能正常加載但LED沒有反應

//可能原因:

// 時序問題(瞎猜),對于一個有作業系統的驅動中的時序問題現在确實有點糊塗。

// 然後把延時注釋掉,還是毫無反應。後來看了實驗手冊,發現這個LED顯示的驅動

// 都已經由CPLD實作了,是以時序不是問題。

//真正原因:

// 原來那個無作業系統的代碼裡面有一個Init_LED_CPLD()函數,該函數對LED的顯示

// 做了使能,原來的檔案中沒有用到led_enable這個宏。

//

//問題2:

//症狀:

// 加載子產品之後,直接出現oops

//可能原因:

// 不知道,瞎猜都猜不出,郁悶。第一次看到oops,這玩意是個頭大的東西阿,刷刷

// 出來一大段東西不知如何是好,搞了很久才發現是這裡少個零真要命。

//真正原因:

// 第10行中的FLAG——INER宏定義少輸入了一個零,由于剛開是代碼比較亂沒能及時發

// 現錯誤,找了很久,不應該阿。要時刻注意代碼規範,這種錯誤一出現就能發現。

//

//問題3:

//症狀:

// 輸出

// 1 1

// 2 2

// 之後出現亂碼,隻能重新開機,LED不能顯示。

//可能原因:

// delay時間太長,可能性不大但想不出更好的原因了。

//真正原因:

// 14-19行中的宏定義有誤,一開始沒有細想,直接想當然的用了long。這個錯誤是我

// 在做一周小結的時候不經意間發現的。改過之後終于看到LED亮了那是興奮阿。。。

//

//問題4:

//症狀:

// 關閉LED顯示,加了led_delete()函數(48-51,99),但led正常關掉但是minicom

// 輸出亂碼,隻能重新開機。

//可能原因:

// 肯定是這個led_delete()在作怪。嘗試讀取FLAG_OE中的資料分别sample_module_i

// -nit(),sample_module_exit(),的開始跟結尾添加了對FLAG_OE的讀取跟顯示。結果

// 子產品一加,led正常顯示,minicom正常輸出之後失去了對控制台的控制(安鍵盤沒反

// 應了)。

//真正原因:

// 仔細看了一下各實驗文檔,led_enable對應的是CPLD與BF533的A9--A15位址引腳

// 相連,不能像記憶體随意進行讀寫,由于不知道CPLD的内部程式隻能猜測led_enable

// 是不可讀的。底50行中的或操作也用到了讀也是一個錯誤,這個讀相對比較隐蔽。

總得來說,所犯的錯誤都是非常細節的,對于那些稍微有點經驗的人來說這些錯誤是非常愚蠢的;對于初學者來說這些錯誤是一道道砍。

有些人發現不了這些錯誤直接放棄,然後這條路就此終止了,有些人即使也發現這些錯誤了,卻會自我懷疑,自己竟然會犯這麼簡單的錯誤是不是不适合幹這行,不用說這些人肯定也是走不遠的。

我現在是憑着一點點運氣跟小小的執着走了過來了,對後面的知識也是充滿這好奇希望自己能在這

條路上走的很遠。覺得,我現在是在犯愚蠢的錯誤但以後再也不會了,‘趁着年輕多犯點錯誤(非原則性錯誤)’還是挺有理的。犯錯是很正常的事,要盡早的犯‘該犯的錯誤’,然後快速成長。

再加一句:以後小有成就了,這些還将成為自嘲的資本,沒種程度上說也是炫耀的資本,有些人不知出于什麼目的還得編一大堆曾經犯下的愚蠢錯誤,而我這個可都是活生生的。