由於選用了 Asynchronous USART Driver, 因此一旦Submit transfer task後App即可馬上做其他事, 但真正的Transfer就必須等到Driver處裡到Queue中的Transfer Request才會發生, 唯一可以攔截Rx/Tx的Driver Transfer Callback卻都是在完成後才會Callback.
如果因為傳送或是接受前需要"同步"做的一些事, 那可以選擇Synchronous USART Driver mode, 則每次傳送及接收時都必須等到完成才會往下做, 這樣就可以在下達Read/Write Transfer前, 先控制DE/~RE pin了, 並且在傳送完成後關閉DE/~RE pin
如果要保有Asynchronous USART Driver的Queue排隊方式時, 目前USART Driver沒有可在Rx/Tx發生前可以插入"Callback"的API, 因為Callback是Interrupt發生時才會做的, 時間點不對也就不是Callback.
正確應該是想辦法在Driver Transfer Queue中, 每次處裡要Read/Write request前, 可以正確地插入DE/~Re pin控制的code才是, 那這樣就必須要去改Gen出的code了!
Harmony 沒有規定不能去改他Gen出來的Code, 很多時候是需要去改的, 所以在Gencode時, 才會有Merge User code的選項, 只是如果自己改了code, 就必須要確保加上去的code不會影響Framework的運作.
以下幾點方向可以嘗試看看
1. 因為 SERCOM PLIB已經被USART Driver給全權管理了, 因此絕對不能再去呼叫SERCOM PLIB下的API不然會造成Driver混亂, 比如去呼叫SERCOMx_USART_WriteCallbackRegister()等等,
2. 可以去Driver中尋找Queue的Transfer Request, 何時被抓出來交給SERCOM PLIB執行 Read/Write, 基本上在這個Moment時的動作幾乎是馬上被PLIB執行的, 因此在這時去控制 DE/~RE pin應該不會有問題, Driver中的static function為 _DRV_USART_ReadSubmit() 與 _DRV_USART_WriteSubmit()
3. 由於 Driver全部使用 Function Pointer來進行操作, 所以可以在Driver initialization時, 查出PLIB的Function在Driver中變成什麼樣子, 這樣比較好找到PLIB在哪個地方被Driver給呼叫執行, code改在這裡就比較safe.
const DRV_USART_PLIB_INTERFACE drvUsart0PlibAPI = {
.readCallbackRegister = (DRV_USART_PLIB_READ_CALLBACK_REG)SERCOM5_USART_ReadCallbackRegister,
.read = (DRV_USART_PLIB_READ)SERCOM5_USART_Read,
.readIsBusy = (DRV_USART_PLIB_READ_IS_BUSY)SERCOM5_USART_ReadIsBusy,
.readCountGet = (DRV_USART_PLIB_READ_COUNT_GET)SERCOM5_USART_ReadCountGet,
.readAbort = (DRV_USART_PLIB_READ_ABORT)SERCOM5_USART_ReadAbort,
.writeCallbackRegister = (DRV_USART_PLIB_WRITE_CALLBACK_REG)SERCOM5_USART_WriteCallbackRegister,
.write = (DRV_USART_PLIB_WRITE)SERCOM5_USART_Write,
.writeIsBusy = (DRV_USART_PLIB_WRITE_IS_BUSY)SERCOM5_USART_WriteIsBusy,
.writeCountGet = (DRV_USART_PLIB_WRITE_COUNT_GET)SERCOM5_USART_WriteCountGet,
.errorGet = (DRV_USART_PLIB_ERROR_GET)SERCOM5_USART_ErrorGet,
.serialSetup = (DRV_USART_PLIB_SERIAL_SETUP)SERCOM5_USART_SerialSetup
};