stm32的swd接口的燒寫協議是否公開的呢?


stm32的swd接口的燒寫協議是否公開的呢?

 

需要用一台好的示波器來抓才能有足夠的存儲深度,保證你能夠過濾掉那個該死的50clock。

按照Arm的手冊,每次轉換發送方都需要一個TNR---但是我觀察JLINK的波形卻沒有那個該死的TNR。

手冊中說異步SWD需要,同步不需要----或者相反,但是我沒有找到關於同步異步的描述。

姑且不管他,反正目前忽略掉TNR就能夠讀到該死IDR。

另外JLINK的復位時序很奇怪,大致是

70clk High,0xe79e(注意,SWD是LSB First),

70clk High,0xedb6(這里很奇怪,找不到描述),

70clkHigh,16clk Low,0xa5,

注意這里按照協議應該是TNR位-但是沒有實際觀測到這個位,

0b100(ACK-OK),0xba01477……

實際測試,不額外增加那個奇怪的0xedb6也能夠照常讀出IDR。

另外要注意,設備端的數據最哈哦在CLK的下降沿讀取,或者上升沿過后延時1/2bit后讀取。

如果想要深究,可以去sourceforge.net去下載SWD Lib,以及openOCD,兩者對照着來會很方便。

利用好bitband寫程序會很舒服,尤其是處理SWD的位流,一個int32指針跳起來很爽,並且是LSB First的結構。

完全沒有任何障礙的。

另外發現在讀IDR后,其他的讀寫命令的ACK后面,SWDIO會有兩個bits的緩慢上升波形,

並且在clk的下降沿被Target拉底,按照格式硬套的話,這兩個位應該忽略掉。

目前還沒發現對於這兩個位的說法。

有的時候能夠看到當JLink讀取信息的最后會把本該由Target發送的parity拉低,忽略掉。

還有需要注意的是,似乎除了讀IDR,CTRL,ABOUT這三個寄存器外,其他的寄存器讀取都有一個數據幀的延遲。

比如你發起第一個讀取貞,讀到的數據沒有意義。

第二個讀取幀,讀到的是第一次的地址對應的數據,依次類推。

硬件上,SWDIO的上拉要足夠強,不然上升沿可能不夠陡峭,我現在用的是2.2k,還湊合。

看到SWD LIB的源碼里面是按照8位讀寫,32位讀寫的方式來做的。

也就是說,只要控制好SWCLK,並且能夠保證不丟掉任何SWDIO位信息,用SPI也可以模擬出SWD的時序。

這部分參考了SourceForge的LibSwd項目,該項目是開源的,寫的很嚴謹,代碼風格也很好,強烈大家下來看看。

原始代碼是四個函數,讀,寫,8,32.我歸結到兩個函數,用了bitband結構所以入口就簡單了一些,緩沖區和位數即可

int iLibSwdMosi(unsigned int* pBits,unsigned int iLen)
{
        unsigned int        i;
        
        for(i=0;i<iLen;i++)
        {
                ToSWCLK                =        def_false;
                ToSWDIO        =        (unsigned char)*pBits++;
                iLibSwdDelay(SWD_BIT_LENGTH);
                
                ToSWCLK                =        def_true;
                iLibSwdDelay(SWD_BIT_LENGTH);
        }
        
        ToSWCLK                        =        def_false;
        ToSWDIO                        =        def_true;
        return(0);
}
int iLibSwdMiso(unsigned int* pBits,unsigned int iLen)
{
        unsigned int        i;
        
        ToSWDIO                =        def_true;
        iLibSwdDelay(SWD_BIT_LENGTH);
        for(i=0;i<iLen;i++)
        {
                ToSWCLK                =        def_true;
                iLibSwdDelay(SWD_BIT_LENGTH);
                
                *pBits++        =        (unsigned int)TiSWDIO;
                ToSWCLK                =        def_false;
                iLibSwdDelay(SWD_BIT_LENGTH);
        }
        return(0);
}

看到return(0)你想到了什么?

嘿嘿,本來我是采用定時器來控制clk的,這樣就需要考慮程序運行出錯的返回代碼。

后來發現這樣很傻,就該成死等了。

這樣就不需要返回異常信息了,但是為了保持形式上的統一,函數還是帶有返回值的樣子。hoho

這里是延時函數,大寫的量是宏定義

int iLibSwdDelay(unsigned int iDly)
{
        unsigned int        i,k;
        
        for(i=0;i<iDly;i++)
        {
                for(k=0;k<SWD_BIT_LENGTH;k++)
                ;
        }
        return(0);
}

這里是切換到SWD模式並且讀取IDR的函數。

int iLibSwdSwitch2SWD(void)
{
        unsigned int i;
        
        for(i=0;i<SWD_SLT_R_CNT;i++)
        {
                iLibSwdPortInit(def_false);
                iLibSwdPortInit(def_true);
                
                for(i=0;i<SWD_RST_H_BYTES;i++)
                        cBitsSwdOutput[i]        =        0xff;
                iLibSwdMosi(iBitAddress(cBitsSwdOutput,0),(SWD_RST_H_BYTES * 8));
                
                cBitsSwdOutput[0]        =        0x9e;
                cBitsSwdOutput[1]        =        0xe7;
                iLibSwdMosi(iBitAddress(cBitsSwdOutput,0),(2 * 8));
                
                for(i=0;i<SWD_RST_H_BYTES;i++)
                        cBitsSwdOutput[i]        =        0xff;
                iLibSwdMosi(iBitAddress(cBitsSwdOutput,0),(SWD_RST_H_BYTES * 8));
/* cBitsSwdOutput[0] = 0xb6; cBitsSwdOutput[1] = 0xed; iLibSwdMosi(iBitAddress(cBitsSwdOutput,0),(2 * 8)); */
vLibSwdLineReset(); cBitsSwdOutput[0] = SWD_HOST_RD_DPIDR; iLibSwdMosi(iBitAddress(cBitsSwdOutput,0),(1 * 8)); cBitsSwdInput[0] = 0; iLibSwdMiso(iBitAddress(cBitsSwdInput,0),3); if((cBitsSwdInput[0] & 0x07) == 0x01) { iLibSwdMiso(iBitAddress(cBitsSwdInput,0),33); return(*(unsigned int*)cBitsSwdInput); } } return(-1); }

 

如果成功讀取會返回一個指針,這個指針對應的緩沖區是預先申請好的,由於程序沒有改完,所以這里還不太好看。大家自己發揮吧。

上面用/**/屏蔽部分就是我說的JLINK波形中很奇怪的地方,屏蔽和不屏蔽在讀取IDR時好像沒什么分別。

不知道JLINK用來做什么的。有知道的么?

有時候為了區別是Host還是Target送出的bit,可以在時序上做一點修整。

Target總是在Clk的上升沿送出數據,Host可以在上升沿前面一點送出數據,

這樣就可以通過示波器來區別到底是Target還是Host發送的0

另外,手冊中有提到,在每個數據幀后面附加幾個額外的clk周期。

JLink的波形上也的確有這樣的體現。不過似乎不是總出現。

暫時沒發現這塊的影響,可能是通用性的考慮吧

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM