s3c2440在linux
『壹』 linux移植s3c2440求助。關於內核選擇等
這個內核應該是隨硬體提供的。而且教程不同針對的內核版本也不同,所以你現在需要板子、內核、教程三部分必須版本一樣。
『貳』 如何在S3C2440上linux操作系統下將串口的波特率提高以致921600
就是把串口的波特率提上去,硬體環境呢,就是採用飛凌的TE2440-II(比較古老了,大家勿噴)操作系統是linux2.6.28,大家都知道,正常情況下,Linux下串口波特率最高到115200,因為我們特殊需要的原因,需要把波特率提高到至少460800,當然最理想的結果就是波特率達到921600,大的背景就是這個樣子了。
然後先考究硬體,看看在硬體上到底能不能滿足我們的要求,主控晶元S3C2440,在UART一章說在系統時鍾下,波特率最高可達115200,然後注釋中說如果Pclk達到60M,可以實現921600,我就按他說的,將主頻提高,順便將pclk提高到了60M,發現921600根本實現不了,230400波特率雖然能通,但是錯誤率很高,根本無法用,然後我又嘗試著將Pclk提高到了70M,通過這種飲鴆止渴的方式,波特率可以提高到230400並且穩定傳輸,但是更高的波特率則無法實現,而Pclk不能無限提高,因為我們開發板還連接了觸摸屏,在Pclk70M的情況下,觸摸屏經常重啟,說明這個方案不可行,所以就pass掉了,下面簡單說一下我怎麼更改的系統時鍾Fclk,Hclk,Pclk。這三個時鍾的關系以及計算方法我就不贅述了,我主要參考博客http://blog.csdn.NET/dong_hong/article/details/8469269進行修改
1)首先找到bootloader中 INC文件夾下的Option.inc文件,打開以後,找到如下代碼段,這段代碼就是主頻400M時對應的M,P和S值設置,需要更改主頻的話更改其中相應的數值幾個(後來我發現,其實這個地方不改也行,因為最終起作用的是第二步)
[ FCLK = 400000000
CLKDIV_VAL EQU5
;1:4:8
M_MDIV EQU
127 ;127
M_PDIV EQU
2 ;2
[ CPU_SEL = 32440001
M_SDIV EQU
1 ; 2440A
|
M_SDIV EQU
0 ; 2440X
]
]
2)找到u2440mon.c,然後在main()函數中找到如下代碼,修改case2中的mpll_val = (92<<12)|(1<<4)|(1);這一行(為啥修改這一行?因為在這個switch代碼有個j=2),其中三個數分別代表M,P,S。這才是決定主頻的關鍵。
switch(j) {
case 0:
//240
key = 14;
mpll_val = (112<<12)|(4<<4)|(1);
break;
case 1:
//320
key = 14;
mpll_val = (72<<12)|(1<<4)|(1);
break;
case 2:
//400
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
case 3:
//420!!!
key = 14;
mpll_val = (97<<12)|(1<<4)|(1);
break;
default:
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
}
3)然後再 2440lib.c文件中,找到 ChangeClockDivider()函數,這個函數是控制分頻比的,代碼如下,這兩個一個控制h_div,一個控制p_div。其中case 18: hdivn=2; break;這一行控制H分頻,具體怎麼改可以參考手冊。
switch(hdivn_val) {
case 11: hdivn=0; break;
case 12: hdivn=1; break;
case 13:
case 16: hdivn=3; break;
case 14:
case 18: hdivn=2; break;
}
switch(pdivn_val) {
case 11: pdivn=0; break;
case 12: pdivn=1; break;
}
只需以上三步,就可以更改系統主頻以及分頻比,得到自己想要的Fclk和Pclk。
然後再說說我把上一個方案否定了以後,再仔細閱讀晶元手冊,發現串口的時鍾源可以有三種方式獲得:pclk,fclk/n,exclk,而且手冊上說採用外部時鍾的話,可以做到更高的波特率,但是這需要更改硬體,從指定那個引腳引入一個時鍾,然後還要更改驅動程序,所以放棄了,所以只剩下一個路可以走,就是採用fclk/n的方式作為串口的時鍾源,因為fclk頻率很高,所以時鍾源提高了,就可以把波特率提上來。然後就開始看linux內核源代碼,因為串口的驅動早就集成到了linux內核之中,然後我就跳進了一個大坑。
其實串口本身的驅動並不復雜,如果裸機開發的話我感覺不難(強調一下,這個串口的裸機開發我沒有做過,請做過的人不要噴我),因為串口被封裝到了linux系統中,並且是層層封裝,最終被封裝成了tty的形式,所以我就從tty的驅動看起,抽絲剝繭,從裡面尋找蛛絲馬跡,
首先發現了s3c2440.c這個文件,通過調試得知,初始化的時候調用了其中的s3c2440_serial_init()函數,剛開始以為在這個文件中就這個函數有用,其實後來才知道,這個文件中的s3c2440_serial_getsource()和s3c2440_serial_setsource()在驅動中多次被調用。
然後考慮到,在上位機設置波特率的時候,調用的是系統函數cfsetispeed(),後經調試得知,這個函數調用了Samsung.c這個文件中的s3c24xx_serial_set_termios()這個函數,所有與串口相關的配置都與這個函數有關,因此鎖定了方向,只要從這個函數中找到與波特率以及時鍾源相關的語句,更改成我想要的即可,而這個函數又調用了很多子函數,但真正與波特率及時鍾源相關的函數就是如下幾句
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
/* check to see if we need to change clock source */
if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
s3c24xx_serial_setsource(port, clksrc);
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
ourport->baudclk = NULL;
}
clk_enable(clk);
ourport->clksrc = clksrc;
ourport->baudclk = clk;
}
其中,uart_get_baud_rate()函數用於計算出上位機程序到設置的波特率的值,經我調試得知,上位機波特率從2400到921600都可以被准確的計算出來;所以這個函數跳過,然後看最後那個if語句,這個語句的作用是產看目前的時鍾源是否與設置的時鍾源相同,如果不相同,則按照設置的時鍾源進行更改,這裡面還涉及linux下的關於管理時鍾的一個結構體clk結構體,參照博客http://blog.chinaunix.Net/uid-26583794-id-3208153.html以及http://wenku..com/view/13b4c686b9d528ea80c77904.html我找到了linux下的mach-smdk2440.c這個文件,這個文件中定義了串口所用的clk結構體,這也是linux系統啟動時對串口的初始化配置結構體都在這,但是我更改過這個地方,讓他初始化配置是首選fclk作為串口的時鍾源,但是我發現這並沒有效果,所以繼續尋找中。
這樣就剩下一個函數可以考慮了,s3c24xx_serial_getclk(),進入這個函數你會發現,這個函數是對串口時鍾及波特率一個全面的配置,進入這個函數中,就有個結構體tmp_clksrc,這個結構體很關鍵,他的內容如下:
static struct s3c24xx_uart_clksrc tmp_clksrc = {
.name = "pclk",
.min_baud
= 0,
.max_baud
= 0,
.divisor
= 1,
};
從這個名字中就可以看出,它把串口的時鍾源內定成為了pclk,這也是罪魁禍首,但是當我把name更改為fclk時,整個系統就無法啟動了,包括前面說的更改mach-smdk2440.c中初始化配置,也是無法啟動,後來在配置串口是做了一個判斷,當波特率低於200000時,才有系統源配置不變,當波特率高於200000時,不在採用tmp_clksrc這個結構體,而是採用我自己定義的一個結構體,當然就是把name改成fclk,發現雖然只是能夠更改 裡面部分參數的時鍾源,而正在的時鍾源還是pclk,說明我的更改根本么有生效,由於這個linux調用太龐雜了,我就抱著試試看的態度,也是沒有辦法的辦法,在配置完串口時鍾的代碼之後,添加了如下幾行代碼,直接更改S3C2440的寄存器,我知道這樣做是很不「道德」的,而且很容易引起系統混亂,但是我只是這么試試,沒想到還真的有用。
在 samsung.c文件中添加
if (baud >= 200000)
{
printk("baud >= 200000 @-------------samsung.c\n");
__raw_writel(0x1fc5,S3C24XX_VA_UART0 + S3C2410_UCON);
__raw_writel(0x0fc5,S3C24XX_VA_UART1 + S3C2410_UCON);
__raw_writel(0x8fc5,S3C24XX_VA_UART2 + S3C2410_UCON);
__raw_writel(32,S3C24XX_VA_UART0 + S3C2410_UCON+0x24);//保證控制台的波特率還是115200用於顯示
__raw_writel(3,S3C24XX_VA_UART1 + S3C2410_UCON+0x24);//921600
//__raw_writel(3,S3C24XX_VA_UART1 + S3C2410_UCON+0x24);
}
上面這段代碼經我多次試驗得到的,因為一開始用的系統主時鍾fclk為400M,這樣算出來UBRDIV1分頻應該為3,但是這樣的話錯誤率比較高,還是導致無法傳輸,至此我終於明白手冊上為什麼說pclk在60M 可以實現921600了,因為用60M時鍾計算的話,分頻UBRDIV1為3.069,最接近整數3,所以在這個錯誤率下可以實現921600的波特率傳輸,所以我將系統時鍾fclk設置為420M,其中MDIV=97,PDIV=1,SDIV=1,而ucon0=0x1fc5,ucon1=0x0fc5,ucon2=0x8fc5,這樣n=1+6=7,所以串口的時鍾源為fclk/n=60M,可以得到精確的921600波特率,所以實現我剛開始的目標,其實要實現其他的波特率也可以,比如460800,計算後主時鍾fclk(盡量算出的分頻UBRDIV1最貼近整數),然後就可以實現了。
在這還有個小想法,提高串口波特率,還可以使用USB轉串口,因為USB轉串口可以實現921600,而linux中以及集成了USB轉串口的驅動,只需要在調用串口的那個open函數中改為調用USB轉串口的節點即可,當然,這個方案我沒有試,因為我們就一個USB口,而且還被佔用了,所以希望有需要的朋友可以試一下。
『叄』 ARM s3c2440-linux如何釋放作為console的ttyS0串口
在你的s3c2440板子上,你的串口節點驅動,可能不是ttys0,這樣的驅動文件,在各個製作系統文件時串口的驅動節點,可能是別的文件名,你仔細的觀察下,給你個建議,我的串口驅動節點是s3c2440-serial這個文件,不是ttys0你看一下是不是這個
『肆』 linux下S3C2440更改硬體時間晶元自己保存不了,改了重啟還是以前的,使用的默認usb口也改不了總是ttyusb0
如果你在命令沒有修改到硬體時間, 那說明你的命令沒有成功操作到時鍾晶元, 你可以看一下目標版的時鍾晶元是哪個型號的, 找到對應的datasheet, 看看該晶元採用什麼匯流排介面連接你的s3c2440, 一般時鍾晶元都用i2c介面, 那麼你可以仿照i2c匯流排規范寫一個操作i2c從設備寄存器的程序, 直接對時鍾晶元的寄存器, 比如分鍾, 小時, 秒,星期,月, 年等寄存器做修改, 這樣硬體時間就會改變了.這是一個可以通用的方法.
至於ttyUSB0, 這個一般是修改不了的, 因為當只有一個USB設備連接到你的系統時, linux默認是將其標記為ttyUSB0的.
你第二個問題是一個正常的現象.
第一個問題你可以這樣驗證一下:
先用date命令修改一下系統時間, 比如date -s "2013-4-28 10:30:00"
之後用hwclock -w 將系統時間同步為硬體時間,
如果成功後應該沒有錯誤信息報錯.
之後再用hwclock -r 讀取硬體時間, 如果為剛剛你設定的時間的話, 那麼說明你的時鍾晶元及驅動沒有問題, 而可能是的操作不對.
如果你在使用hwclock 時候, 有這樣的報錯:
root@juson:~# hwclock -w
hwclock: open() of /dev/rtc failed, errno=2: No such file or directory.
這是因為 hwclock 默認打開/dev/rtc 這個文件, 但是你的linux可能將時鍾晶元掛載/dev/rtc0 上,
這樣可以:
ln -s /dev/rtc0 /dev/rtc
之後的操作就因該沒問題了, 你看下我的記錄:
//修改系統時間
root@juson:~# date -s "2013-4-28 10:30:00"
Sun Apr 28 10:30:00 CST 2013
root@juson:~#
//同步為硬體時間
root@juson:~# hwclock -w
hwclock: open() of /dev/rtc failed, errno=2: No such file or directory.
//使用ln 解決這個問題
root@juson:~# ln -s /dev/rtc0 /dev/rtc
root@juson:~#
//再次同步就ok了
root@juson:~# hwclock -w
root@juson:~#
//獲取硬體時間
root@juson:~# hwclock -r
Sun Apr 28 10:36:28 2013 -0.617634 seconds
以上就成功地修改了硬體時間.
『伍』 我是天嵌s3c2440的板子,現在Linux移植,一直按廠家手冊做的,可是make menuconfig的時候總是出現如下錯誤
/bin/sh: line 1: gcc: command not found
注意提示,是 gcc 這個命令未找到,而不是 arm-linux-gcc 這個命令未找到。
而且再看第一行提示
HOSTCC scripts/basic/fixdep
這行裡面的 HOSTCC ,HOST 一般對於 Linux 來說是本地的東西意思,也就是說這行用的是當前系統使用的 cc (這個 cc 是 C Compiler 的意思,gcc 命令是 GNU Compiler Collection 的 cc )。也就是說,當前系統的 gcc (一般習慣下沒有前綴的 gcc 就是本地 GCC )沒有找到。
所以充分表明你根本不會 Linux 就去弄嵌入式……
『陸』 我的s3c2440開發板安裝的linux系統沒有data命令,我現在想安裝這個命令誰知道該怎麼做嗎謝謝了!
你可以編寫一個程序生成二進制放到/bin目錄下,或者編寫shell腳本。
『柒』 s3c2440linux 下怎麼寫外接dac的控製程序
linux 為了保護核心文件root沒有開啟 通過下面方式設置sudo passwd root 回車(輸入密碼,但不會在屏幕顯示出*)(再輸入一次密碼)然後 root 登陸
『捌』 北京楊創科技s3c2440,我想裝成linux,按照開發手冊上把uboot通過wiggler寫進去後,
是從nand 啟動的還是nor啟動的,一般nand啟動的話就直接啟動linux了,不會進入uboot,試試nand啟動時點擊空格,(我的開發板是點擊空格),也可以從nor啟動。