1. 程式人生 > >高通平臺串列埠除錯 AP與模組串列埠通訊除錯總結 uart

高通平臺串列埠除錯 AP與模組串列埠通訊除錯總結 uart

高通平臺串列埠除錯 AP與模組串列埠通訊除錯總結

2016年07月07日 18:03:41

閱讀數:3144

原文網址:http://blog.csdn.net/linux_devices_driver/article/details/24329043

1:檢查AP端串列埠配置是否ok:

a:高通平臺檢視DMA傳輸:

echo 1 > /sys/kernel/debug/msm_serial_hsl/loopback.0 //打開回環開關

adb shell cat /dev/ttyHSL1

另起視窗

# adb shell

# echo 11111111 > /dev/ttyHSL1

若DMA通道ok,控制檯會迴圈顯示;

b:檢視uart gpio是否ok:

tx高電平、rfr為低電平,rx,cts為輸入;       

如果tx為低電平,那麼gpio肯定沒有配置好,再次檢查gpio配置問題;

如果以上2步都ok,那麼UART應該ok了,再次檢查:

adb shell cat /dev/ttyHSL1

將TX與RX短接;

另起視窗

# adb shell

# echo 11111111 > /dev/ttyHSL1

迴圈顯示那麼恭喜UART功能配置好了。

2:Termios引數配置:

影響通訊資料格式的關鍵

幾個引數:

1:波特率-speed,通常

115200,最高4M;

2:奇偶校驗-Parity,通

常為None;

3:資料位-Data,通常

8bit;

4:停止位-Stopbits,通

常1bit;

一般情況下預設為115200 8N1,也就是波特率115200,8bit資料位,無奇偶校驗,1bit停止位。

為了使得AP可以與模組串列埠通訊,必須先了解模組的termios設定。

Ap端termios設定:

首先應用開啟串列埠時會設定termios:

  1. termios.c_cflag &= ~CSIZE;  
  2. termios.c_cflag |= CS8;  
  3. termios.c_cflag &= ~CSTOPB;  
  4. termios.c_cflag &= ~PARENB;  
  5. termios.c_cflag &= ~CBAUD;  
  6. termios.c_cflag |= B3000000;   
  7. termios.c_cflag |= CREAD | CLOCAL;  
  8. termios.c_cflag |= CRTSCTS; /* turn on hardware flow control */  
  9. termios.c_iflag &= ~(IXOFF | IXON | IXANY); /* soft flow control */  

驅動介面會根據termios引數來設定底層串列埠:

以8064 msm_seriel_hs.c為例說明:

uart介面封裝:

  1. static struct uart_ops msm_hs_ops = {  
  2. .tx_empty = msm_hs_tx_empty,  
  3. .set_mctrl = msm_hs_set_mctrl_locked,  
  4. .get_mctrl = msm_hs_get_mctrl_locked,  
  5. .stop_tx = msm_hs_stop_tx_locked,  
  6. .start_tx = msm_hs_start_tx_locked,  
  7. .stop_rx = msm_hs_stop_rx_locked,  
  8. .enable_ms = msm_hs_enable_ms_locked,  
  9. .break_ctl = msm_hs_break_ctl,  
  10. .startup = msm_hs_startup,  
  11. .shutdown = msm_hs_shutdown,  
  12. .set_termios = msm_hs_set_termios,  
  13. .type = msm_hs_type,  
  14. .config_port = msm_hs_config_port,  
  15. .release_port = msm_hs_release_port,  
  16. .request_port = msm_hs_request_port,  
  17. .flush_buffer = msm_hs_flush_buffer_locked,  
  18. };  

下面是底層設定函式,上層開啟串列埠,引數未固定的話驅動走的是8N1,底層除錯只使用echo或者cat /dev/ttyHSL0時

波特率一律是9600,模組不是9600時那麼通訊肯定會失敗,所以AP需要根據模組重新設定。

波特率。

//設定termios介面

  1. /*  
  2. * termios : new ktermios  
  3. * oldtermios: old ktermios previous setting  
  4. *  
  5. * Configure the serial port  
  6. */  
  7. static void msm_hs_set_termios(struct uart_port *uport,  
  8. struct ktermios *termios,  
  9. struct ktermios *oldtermios)  
  10. {  
  11. unsigned int bps;  
  12. unsigned long data;  
  13. unsigned long flags;  
  14. int ret;  
  15. unsigned int c_cflag = termios->c_cflag;  
  16. struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);  
  17. mutex_lock(&msm_uport->clk_mutex);  
  18. spin_lock_irqsave(&uport->lock, flags);  
  19. /*  
  20. * Disable Rx channel of UARTDM  
  21. * DMA Rx Stall happens if enqueue and flush of Rx command happens  
  22. * concurrently. Hence before changing the baud rate/protocol  
  23. * configuration and sending flush command to ADM, disable the Rx  
  24. * channel of UARTDM.  
  25. * Note: should not reset the receiver here immediately as it is not  
  26. * suggested to do disable/reset or reset/disable at the same time.  
  27. */  
  28. data = msm_hs_read(uport, UARTDM_DMEN_ADDR);  
  29. data &= ~UARTDM_RX_DM_EN_BMSK;  
  30. msm_hs_write(uport, UARTDM_DMEN_ADDR, data);  
  31. /* 300 is the minimum baud support by the driver */  
  32. bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000);  
  33. /* Temporary remapping 200 BAUD to 3.2 mbps */  
  34. if (bps == 200)  
  35. bps = 3200000;  
  36. uport->uartclk = clk_get_rate(msm_uport->clk);  
  37. if (!uport->uartclk)  
  38. msm_hs_set_std_bps_locked(uport, bps);  
  39. else  
  40. flags = msm_hs_set_bps_locked(uport, bps, flags);//函式裡面設定baud;  
  41. data = msm_hs_read(uport, UARTDM_MR2_ADDR);  
  42. data &= ~UARTDM_MR2_PARITY_MODE_BMSK;  
  43. /* set parity */ //設定奇偶校驗  
  44. if (PARENB == (c_cflag & PARENB)) {  
  45. if (PARODD == (c_cflag & PARODD)) {  
  46. data |= ODD_PARITY;  
  47. } else if (CMSPAR == (c_cflag & CMSPAR)) {  
  48. data |= SPACE_PARITY;  
  49. } else {  
  50. data |= EVEN_PARITY;  
  51. }  
  52. }  
  53. /* Set bits per char */       //設定資料位  
  54. data &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;  
  55. switch (c_cflag & CSIZE) {  
  56. case CS5:  
  57. data |= FIVE_BPC;  
  58. break;  
  59. case CS6:  
  60. data |= SIX_BPC;  
  61. break;  
  62. case CS7:  
  63. data |= SEVEN_BPC;  
  64. break;  
  65. default:  
  66. data |= EIGHT_BPC;  
  67. break;  
  68. }  
  69. /* stop bits */ //設定停止位  
  70. if (c_cflag & CSTOPB) {  
  71. data |= STOP_BIT_TWO;  
  72. } else {  
  73. /* otherwise 1 stop bit */  
  74. data |= STOP_BIT_ONE;  
  75. }  
  76. data |= UARTDM_MR2_ERROR_MODE_BMSK;  
  77. /* write parity/bits per char/stop bit configuration */  
  78. msm_hs_write(uport, UARTDM_MR2_ADDR, data);  
  79. /* Configure HW flow control */ //設定是否使用硬體流控  
  80. data = msm_hs_read(uport, UARTDM_MR1_ADDR);  
  81. data &= ~(UARTDM_MR1_CTS_CTL_BMSK |  
  82. UARTDM_MR1_RX_RDY_CTL_BMSK);  
  83. if (c_cflag & CRTSCTS) {  
  84. data |= UARTDM_MR1_CTS_CTL_BMSK;  
  85. data |= UARTDM_MR1_RX_RDY_CTL_BMSK;  
  86. }  
  87. msm_hs_write(uport, UARTDM_MR1_ADDR, data);  
  88. uport->ignore_status_mask = termios->c_iflag & INPCK;  
  89. uport->ignore_status_mask |= termios->c_iflag & IGNPAR;  
  90. uport->ignore_status_mask |= termios->c_iflag & IGNBRK;  
  91. uport->read_status_mask = (termios->c_cflag & CREAD);  
  92. msm_hs_write(uport, UARTDM_IMR_ADDR, 0);  
  93. /* Set Transmit software time out */  
  94. uart_update_timeout(uport, c_cflag, bps);  
  95. msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);  
  96. msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);  
  97. if (msm_uport->rx.flush == FLUSH_NONE) {  
  98. wake_lock(&msm_uport->rx.wake_lock);  
  99. msm_uport->rx.flush = FLUSH_IGNORE;  
  100. /*  
  101. * Before using dmov APIs make sure that  
  102. * previous writel are completed. Hence  
  103. * dsb requires here.  
  104. */  
  105. mb();  
  106. msm_uport->rx_discard_flush_issued = true;  
  107. /* do discard flush */  
  108. msm_dmov_flush(msm_uport->dma_rx_channel, 0);  
  109. spin_unlock_irqrestore(&uport->lock, flags);  
  110. pr_debug("%s(): wainting for flush completion.\n",  
  111. __func__);  
  112. ret = wait_event_timeout(msm_uport->rx.wait,  
  113. msm_uport->rx_discard_flush_issued == false,  
  114. RX_FLUSH_COMPLETE_TIMEOUT);  
  115. if (!ret)  
  116. pr_err("%s(): Discard flush completion pending.\n",  
  117. __func__);  
  118. spin_lock_irqsave(&uport->lock, flags);  
  119. }  
  120. msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);  
  121. mb();  
  122. spin_unlock_irqrestore(&uport->lock, flags);  
  123. mutex_unlock(&msm_uport->clk_mutex);  
  124. }  

3:串列埠通訊問題總結:

遇見過模組不能響應AP的問題:

1:硬體流控問題,若模組使用了硬體流控,配置rfr與cts,使得模組認為

AP準備好了,可以傳送資料了。

2:AP端波特率沒有與模組匹配上,要是懷疑AP波特率設定是否ok,可以將串列埠線連線TX,

設定termios 波特率來看輸出是否ok,這種方法還可以測試驗證AP端各個波特率是否OK,我使用的

minicon可以驗證到460800