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行中的或操作也用到了讀也是一個錯誤,這個讀相對比較隐蔽。
總得來說,所犯的錯誤都是非常細節的,對于那些稍微有點經驗的人來說這些錯誤是非常愚蠢的;對于初學者來說這些錯誤是一道道砍。
有些人發現不了這些錯誤直接放棄,然後這條路就此終止了,有些人即使也發現這些錯誤了,卻會自我懷疑,自己竟然會犯這麼簡單的錯誤是不是不适合幹這行,不用說這些人肯定也是走不遠的。
我現在是憑着一點點運氣跟小小的執着走了過來了,對後面的知識也是充滿這好奇希望自己能在這
條路上走的很遠。覺得,我現在是在犯愚蠢的錯誤但以後再也不會了,‘趁着年輕多犯點錯誤(非原則性錯誤)’還是挺有理的。犯錯是很正常的事,要盡早的犯‘該犯的錯誤’,然後快速成長。
再加一句:以後小有成就了,這些還将成為自嘲的資本,沒種程度上說也是炫耀的資本,有些人不知出于什麼目的還得編一大堆曾經犯下的愚蠢錯誤,而我這個可都是活生生的。