已经做了将近20天了吧,今天总算是把程序在从机上实现了,今天写博客和大家分享下。
所用的主机是STM32C8T6,从机是MSP430,现在实现的功能是通过模拟JTAG协议,把点亮LED灯的程序下载进从机,并且能够控制从机的LED亮。
一: 首先说下所用到的工具,文档和相关代码。
1.最重要的文档是英文文档《430 Memory Programming User's Guide》,里面有用JTAG协议的对从机编程的IO,函数功能,指令介绍和相关JTAG协议时序,TAP状态机。我还找到了中文的文档,在TI官网下载的《通过 JTAG接口进行 MSP430™ 编程》,也可以在我的博客里面下载。
2.还有一个特别实用的源码(JTAG功能函数源码),也是在TI官网下载的,名字是(SLAU320源代码),JTAG文档里面的所有函数,指令都在代码里面,同样可以在我的博客里面下载,名字是《JTAG时序函数源代码》,用IAR for MSP430 打开。
3.其次就是逻辑分析仪,MSP430编程器,用逻辑分析仪对编程器的时序进行分析,模仿他的时序。
二:下面说下我的开发历程,首先这是我的毕业设计,用STM32C8T6对MSP430进行脱机编程,模仿别人的编程器的JTAG时序,用自己的单片机做。
首先要明白怎么做脱机编程,主要有两大步:
1.首先用下载字库的程序,上位机把需要的目标代码下载进主机的FLASH中。
2.把目标代码通过主机模拟的JTAG时序下载进从机中。
第一步不用多说,下载进FLASH中而已,第二步才是难点,下面进行分析。
1.需要明白主机来模拟JTAG时序,主机用普通的IO口来控制JTAG时序,主要控制4个IO口(TDO,TDI,TCK,TMS),还有两个RST和TEST,通过控制着6个IO口就可以模拟JTAG时序了,从机是标准的JTAG接口。
2. JTAG协议就是用来控制从机的CPU的,通过TAP状态机的流程往CPU中写指令和数据,通过这些指令和数据来控制CPU,从而控制CPU所控制的外设,比如复位CPU,中断CPU,让CPU处于指令获取状态,擦除FLASH,往FLASH中写数据,设置程序计数器,读FLASH中的数等等。
3.模拟JTAG时序还要知道TAP状态机(如图1)如何运转的,主要说下通过TMS拉高,TCK经过6个时钟脉冲之后,TMS再拉低就可以到TAP机的Test-Logic-Reset状态,然后让TMS=0(即拉低,切记在TCK的上升沿TMS的值才有效)进入Run-Test/IDLE状态,再让TMS=1进入Select DR-Scan,再让TMS=1进入Select IR-Scan,TMS=0进入Capture-IR,TMS=0进入shift-IR,此时就可以往CPU中写指令,来控制CPU,指令都是8位,在8个TCK的上升沿TDI依次输入每一位指令(切记指令是低位先行)(如图二),然后依次进入Exit1-IR,Updata-IR最后TMS=0回到Run-Test/IDLE,进行下一次写指令或者数据,写数据不做详解,时序如(图三)。
图一 (图片来自《通过 JTAG接口进行 MSP430™ 编程》)
图二(图片来自《通过 JTAG接口进行 MSP430™ 编程》)
图三(图片来自《通过 JTAG接口进行 MSP430™ 编程》)
4. 现在应该知道如何往IR,DR寄存器中如何写数据了吧,下面介绍各个函数,这些函数在JTAG功能函数里面都有,自己看下载看。
// Low level JTAG functions
word DR_Shift16(word Data);
word IR_Shift(byte Instruction);
void ResetTAP(void);
word ExecutePOR(void);
word SetInstrFetch(void);
void SetPC(word Addr);
void HaltCPU(void);
void ReleaseCPU(void);
word VerifyPSA(word StartAddr, word Length, word *DataArray);
// High level JTAG functions
word GetDevice(void);
void ReleaseDevice(word Addr);
void WriteMem(word Format, word Addr, word Data);
void WriteMemQuick(word StartAddr, word Length, word *DataArray);
void WriteFLASH(word StartAddr, word Length, word *DataArray);
word WriteFLASHallSections(const unsigned int *data, const unsigned long *address, const unsigned long *length_of_sections, const unsigned long sections);
word ReadMem(word Format, word Addr);
void ReadMemQuick(word StartAddr, word Length, word *DataArray);
void EraseFLASH(word EraseMode, word EraseAddr);
word EraseCheck(word StartAddr, word Length);
word VerifyMem(word StartAddr, word Length, word *DataArray);
word BlowFuse(void);
word IsFuseBlown(void);
void UnlockInfoA(void);
5.我点亮LED灯使用的使用的han函数如下:
TMS=1;
TCK=1;
TDI=1;
RST=1;
TRST=1;
SysTick_Delay_Ms(10);
TRST=0;
TRST=1;
TRST=0;
SysTick_Delay_Us(16);
TRST=1;
SysTick_Delay_Us(6);
TRST=0;
SysTick_Delay_Us(4);
TRST=1;
TRST=0;
SysTick_Delay_Us(44);
TRST=1;
/
RST=0;
RST=1;
RST=0;
RST=1;
RST=0;
///
SysTick_Delay_Ms(1);
TRST=0;
TRST=1;
TRST=0;
SysTick_Delay_Us(7);
TRST=1;
///
RST=1;
RST=0;
RST=1;
前面这一部分是我模仿编辑器对RST和TRST进行控制的时序,必须要加的。下面进入JTAG的复位,在JTAG_Reset让TAP机复位检查熔丝,然后让CPU在JTAG的控制下,这些函数在源码里面都有,必须要看哦!
SysTick_Delay_Ms(20);
JTAG_Reset();
Under_JTAG();
ReadMem(0x0FF0);
Reset_CPU();
WriteMem(0x0120, 0x5A80);
SysTick_Delay_Ms(7);
//第二部分,擦除整个FLASH
EraseFLASH(0xA500,0xA506,0xFE00,10600);
SysTick_Delay_Ms(2);
//第三部分 把需要的程序存储在数组中写到FLASH中
WriteFLASH(0xF000,40, LED);
//设置程序ji计数器
SetPC(0xEFFC);
//设置CPU为指令获取状态
SetInstrFetch();
TDI=1;
DR_Shift16(0x0000);
//读取所写的程序是否正确
ReadMemQuick(40);
SysTick_Delay_Ms(2);
//第四部分
WriteFLASH(0xFFF0,8,addr1);
SetPC(0xFFEC);
SetInstrFetch();
TDI=1;
DR_Shift16(0x0000);
ReadMemQuick(8);
//结束时对gege各个引脚的控制
End_sequence();
到这里点亮LED灯就能实现了,当然这些都是我模仿MSP430编辑器所写出来的时序,最重要的是学会了JTAG协议,一定要把我前面说的文档,源码,还有逻辑分析仪分析出的时序完全搞懂才可以,读完文档,再结合着时序就会发现很简单,时序完全按照文档写出来的,每个函数,指令都体现在时序中了,最后根据源码里的函数写程序。
现在还不算做完,还要写上位机,还要对hex文件处理,转换等等,大家一起加油,哪里不足的还请多多指教。