linux下让cp2102支持高于921600bps波特率的方法
本文主要介紹通過修改內核驅動的方法,使得cp2102支持高于921600bps波特率的方法。
1、windows下使用cp2102 usb轉ttl模塊調試rk3588板卡(默認波特率為1500000),putty能正常輸入輸出。
2、linux下使用cp2102 usb轉ttl模塊調試rk3588板卡(默認波特率為1500000)的時候,putty和minicom輸出均為亂碼。通過minicom修改波特率為1500000bps,2000000bps等高于1000000bps時,通過示波器測得的波形頻率均為925.9kHz,沒有變化,基本懷疑是linux驅動的限制。于是通過閱讀產品手冊和Linux驅動代碼來解釋該現象,并通過修改驅動的方法,讓cp2102支持更高的波特率。
官方手冊給出cp2102支持的波特率如下表所示:
?官方手冊給出cp2104的波特率如下表所示:
并且相關波特率的計算方法如下圖所示:
cp210x linux下的驅動文件為(drivers/usb/serial/cp210x.c),根據內核版本下載對應的文件到本地,內核通過下列代碼實現波特率修改。
/** CP2101 supports the following baud rates:** 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,* 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600** CP2102 and CP2103 support the following additional rates:** 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,* 576000** The device will map a requested rate to a supported one, but the result* of requests for rates greater than 1053257 is undefined (see AN205).** CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,* respectively, with an error less than 1%. The actual rates are determined* by** div = round(freq / (2 x prescale x request))* actual = freq / (2 x prescale x div)** For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps* or 1 otherwise.* For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1* otherwise.*/ static void cp210x_change_speed(struct tty_struct *tty,struct usb_serial_port *port, struct ktermios *old_termios) {struct usb_serial *serial = port->serial;struct cp210x_serial_private *priv = usb_get_serial_data(serial);u32 baud;/** This maps the requested rate to the actual rate, a valid rate on* cp2102 or cp2103, or to an arbitrary rate in [1M, max_speed].** NOTE: B0 is not implemented.*/baud = clamp(tty->termios.c_ospeed, priv->min_speed, priv->max_speed);if (priv->use_actual_rate)baud = cp210x_get_actual_rate(baud);else if (baud < 1000000)baud = cp210x_get_an205_rate(baud);dev_dbg(&port->dev, "%s - setting baud rate to %u\n", __func__, baud);if (cp210x_write_u32_reg(port, CP210X_SET_BAUDRATE, baud)) {dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);if (old_termios)baud = old_termios->c_ospeed;elsebaud = 9600;}tty_encode_baud_rate(tty, baud, baud); }在use_actual_rate為true的情況下通過cp210x_get_rate_rate獲取,否則通過cp210x_get_an205_rate來獲取。
static const struct cp210x_rate cp210x_an205_table1[] = {{ 300, 300 },{ 600, 600 },{ 1200, 1200 },{ 1800, 1800 },{ 2400, 2400 },{ 4000, 4000 },{ 4800, 4803 },{ 7200, 7207 },{ 9600, 9612 },{ 14400, 14428 },{ 16000, 16062 },{ 19200, 19250 },{ 28800, 28912 },{ 38400, 38601 },{ 51200, 51558 },{ 56000, 56280 },{ 57600, 58053 },{ 64000, 64111 },{ 76800, 77608 },{ 115200, 117028 },{ 128000, 129347 },{ 153600, 156868 },{ 230400, 237832 },{ 250000, 254234 },{ 256000, 273066 },{ 460800, 491520 },{ 500000, 567138 },{ 576000, 670254 },{ 921600, UINT_MAX } };/** Quantises the baud rate as per AN205 Table 1*/ static speed_t cp210x_get_an205_rate(speed_t baud) {int i;for (i = 0; i < ARRAY_SIZE(cp210x_an205_table1); ++i) {if (baud <= cp210x_an205_table1[i].high)break;}return cp210x_an205_table1[i].rate; }static speed_t cp210x_get_actual_rate(speed_t baud) {unsigned int prescale = 1;unsigned int div;if (baud <= 365)prescale = 4;div = DIV_ROUND_CLOSEST(48000000, 2 * prescale * baud);baud = 48000000 / (2 * prescale * div);return baud; }cp210x_get_an205_rate獲取表格指定的波特率,cp210x_get_rate_rate則是用cp2104給定的baud rate generation公式計算波特率和時鐘分頻比。
對于cp2102,波特率最大為921600bps,use_actual_rate為false;對于cp2104,波特率最大為2000000bps,use_actual_rate為true。
為了讓cp2102像cp2104一樣支持任意的波特率,對驅動稍作修改(cp2102和cp2014設置同樣的參數)就可以達到,修改后的代碼如下:
static void cp210x_init_max_speed(struct usb_serial *serial) {struct cp210x_serial_private *priv = usb_get_serial_data(serial);bool use_actual_rate = false;speed_t min = 300;speed_t max;switch (priv->partnum) {case CP210X_PARTNUM_CP2101:max = 921600;break; case CP210X_PARTNUM_CP2103:max = 1000000;break;case CP210X_PARTNUM_CP2102:case CP210X_PARTNUM_CP2104:use_actual_rate = true;max = 2000000;break;case CP210X_PARTNUM_CP2108:max = 2000000;break;case CP210X_PARTNUM_CP2105:if (cp210x_interface_num(serial) == 0) {use_actual_rate = true;max = 2000000; /* ECI */} else {min = 2400;max = 921600; /* SCI */}break;case CP210X_PARTNUM_CP2102N_QFN28:case CP210X_PARTNUM_CP2102N_QFN24:case CP210X_PARTNUM_CP2102N_QFN20:use_actual_rate = true;max = 3000000;break;default:max = 2000000;break;}priv->min_speed = min;priv->max_speed = max;priv->use_actual_rate = use_actual_rate; }編譯和安裝新修改的驅動:
1、建立Makefile文件,編譯生成cp210x.ko
obj-m := cp210x.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all:$(MAKE) -C $(KDIR) M=$(PWD) modules clean:rm -rf *.o *.ko2、安裝
卸載已經加載的驅動
sudo rmmod cp210x
將系統原有的驅動改名
sudo mv /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/cp210x.ko?/lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/cp210x_old.ko
將新編譯驅動copy到制定目錄
將新編譯的驅動拷貝到ib/modules/$(shell uname -r)/kernel/drivers/usb/serial/cp210x.ko?
安裝驅動(重啟系統會自動安裝)
sudo insmod cp210x.ko
如果提示驅動未簽名,可以通過bios關掉系統的安全啟動。
總結
以上是生活随笔為你收集整理的linux下让cp2102支持高于921600bps波特率的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 破解版matlab安装Higher Or
- 下一篇: ISPRS_Potsdam,Vaihin