古詩詞大全網 - 成語故事 - 如何在S3C2440上linux操作系統下將串口的波特率提高以致921600

如何在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。這三個時鐘的關系以及計算方法我就不贅述了,我主要參考博客/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口,而且還被占用了,所以希望有需要的朋友可以試壹下。