[共享][交流][7-27-08 updata]AVR32 JTAG常用指令时序核心代码整理贴
>>基础时序函数:TAP状态机控制1http://cache.amobbs.com/bbs_upload782111/files_9/ourdev_225637.gif
/***********************************************************
* 函数说明:JTAG TAP 状态机控制函数 *
* 输入: 控制序列,序列长度 *
* 输出: 无 *
* 调用函数:无 *
* -------------------------------------------------------- *
* 使用说明 *
* 1、 TMS在TCK上升边沿输出状态控制量。 *
* 2、 连续5个TCK周期在TMS上输出高电平将进入Test- *
* Logic-Reset模式。 *
* 3、 使用该函数时,请将状态机跳转以后TMS需要保*
* 持的电平也作为一个有效输入加入到序列的末尾 *
* 但描述序列长度的数值不需要相应的增加。 *
***********************************************************/
void JTAG_TAP_Control(UINT8 chCTRStream,UINT8 chLength)
{
UINT8 n = 0;
//状态机控制序列
for (n = 0;n < chLength;n++)
{
CLR_TCK
if (chCTRStream & BIT(n))
{
SET_TMS
}
else
{
CLR_TMS
}
JTAG_CLOCK_DELAY
SET_TCK
/* 延时部分 */
JTAG_CLOCK_DELAY
}
//保持电平
if (chCTRStream & BIT(chLength))
{
SET_TMS
}
else
{
CLR_TMS
}
}
# define JTAG_TAP_TEST_LOGIC_RESET JTAG_TAP_Control(0x1F,6);
# define JTAG_TAP_SHIFT_IR JTAG_TAP_Control(0x03,4);
# define JTAG_TAP_RETURN_RUN_TEST_IDEL JTAG_TAP_Control(0x01,2);
# define JTAG_TAP_ENTER_SHIFT_DR_FROM_SHIFT_IRJTAG_TAP_Control(0x03,4);
# define JTAG_TAP_SHIFT_DR JTAG_TAP_Control(0x01,3); >>基础时序函数:发送数据(小端对齐)
/***********************************************************
* 函数说明:小端系统中发送大端数据函数 *
* 输入: 交换数据用的输入输出缓冲,发送的二进制位长度 *
* 输出: 无 *
* 调用函数:无 *
***********************************************************/
void JTAG_Shift_BigEnding_Data
(
BYTE *pchOutBuffer,
BYTE *pchInBuffer,
UINT16 wLength,
UINT8 chOffSet
)
{
UINT8 n = 0;
BYTE chSendData = 0;
BYTE chReceiveData = 0;
UINT16 wByteCount = (wLength & (BIT(3) - 1))
? ((wLength >> 3) + 1) : (wLength >> 3);
if (
(wLength == 0) ||
((pchOutBuffer == NULL) && (pchInBuffer == NULL))
)
{
//无效的输入
return ;
}
/*有待修改*/
CLR_TMS
SHIFT_DAISY_CHAIN_UNIT(g_DaisyChain.chUnitsAfter);
while(wByteCount > 1)
{
wByteCount--;
//发送一个字节
{
if (pchOutBuffer != NULL)
{
chSendData = pchOutBuffer;
}
else
{
chSendData = 0;
}
chReceiveData = 0;
for (n = 0;n < 8;n++)
{
if (chOffSet)
{
chOffSet--;
chSendData >>= 1;
}
else
{
CLR_TCK
//设置TDI
if (chSendData & BIT(0))
{
SET_TDI
}
else
{
CLR_TDI
}
chSendData >>= 1;
//上升沿送出TDI数据
/* 延时部分 */
JTAG_CLOCK_DELAY
SET_TCK
//读取TDO数据
chReceiveData |= (READ_TDO << n);
}
/* 延时部分 */
JTAG_CLOCK_DELAY
}
if (pchInBuffer != NULL)
{
pchInBuffer = chReceiveData; //保存收到的数据
}
}
}
//发送最后一个字节
wLength = (wLength & (BIT(3) - 1))
? (wLength & (BIT(3) - 1)) : 8;
//发送最后几个二进制位
if (pchOutBuffer != NULL)
{
chSendData = pchOutBuffer;
}
else
{
chSendData = 0;
}
chReceiveData = 0;
n = 0;
while(wLength--)
{
if (chOffSet)
{
chOffSet--;
}
else
{
if (wLength == 0)
{
/* 处理Daisy Chain */
SHIFT_DAISY_CHAIN_UNIT(g_DaisyChain.chUnitsBefore);
SET_TMS
}
CLR_TCK
//设置TDI
if (chSendData & BIT(0))
{
SET_TDI
}
else
{
CLR_TDI
}
chSendData >>= 1;
//上升沿送出TDI数据
/* 延时部分 */
JTAG_CLOCK_DELAY
SET_TCK
//读取TDO数据
chReceiveData |= (READ_TDO << n);
}
n++;
/* 延时部分 */
JTAG_CLOCK_DELAY
}
if (pchInBuffer != NULL)
{
pchInBuffer = chReceiveData;
}
} >>基础时序函数:发送数据(大端对齐)
/***********************************************************
* 函数说明:数据交换函数 *
* 输入: 交换数据用的输入输出缓冲,发送的二进制位长度 *
* 输出: 无 *
* 调用函数:无 *
***********************************************************/
void JTAG_Shift_Data
(
BYTE *pchOutBuffer,
BYTE *pchInBuffer,
UINT16 wLength,
BOOL bIfInstruction
)
{
UINT8 n = 0;
BYTE chSendData = 0;
BYTE chReceiveData = 0;
UINT16 wByteCount = (wLength & (BIT(3) - 1))
? ((wLength >> 3) + 1) : (wLength >> 3);
if (
(wLength == 0) ||
((pchOutBuffer == NULL) && (pchInBuffer == NULL))
)
{
//无效的输入
return ;
}
CLR_TMS
if (bIfInstruction)
{
SHIFT_DAISY_CHAIN_BIT(g_DaisyChain.chBitsAfter);
}
else
{
SHIFT_DAISY_CHAIN_UNIT(g_DaisyChain.chUnitsAfter);
}
#ifdef _USE_COMPLETED_EDITION
while(wByteCount > 1)
{
wByteCount--;
//发送一个字节
{
if (pchOutBuffer != NULL)
{
chSendData = *pchOutBuffer++;
}
else
{
chSendData = 0;
}
chReceiveData = 0;
for (n = 0;n < 8;n++)
{
CLR_TCK
//设置TDI
if (chSendData & BIT(0))
{
SET_TDI
}
else
{
CLR_TDI
}
chSendData >>= 1;
/* 延时部分 */
JTAG_CLOCK_DELAY
//上升沿送出TDI数据
SET_TCK
//读取TDO数据
chReceiveData |= (READ_TDO << n);
/*延时部分*/
JTAG_CLOCK_DELAY
}
if (pchInBuffer != NULL)
{
*pchInBuffer++ = chReceiveData; //保存收到的数据
}
}
}
#endif
//发送最后一个字节
wLength = (wLength & (BIT(3) - 1))
? (wLength & (BIT(3) - 1)) : 8;
//发送最后几个二进制位
if (pchOutBuffer != NULL)
{
chSendData = *pchOutBuffer;
}
else
{
chSendData = 0;
}
chReceiveData = 0;
n = 0;
while(wLength--)
{
if (wLength == 0)
{
/* 处理菊花链 */
if (bIfInstruction)
{
SHIFT_DAISY_CHAIN_BIT(g_DaisyChain.chBitsBefore);
}
else
{
SHIFT_DAISY_CHAIN_UNIT(g_DaisyChain.chUnitsBefore);
}
SET_TMS
}
CLR_TCK
//设置TDI
if (chSendData & BIT(0))
{
SET_TDI
}
else
{
CLR_TDI
}
chSendData >>= 1;
/* 延时部分 */
JTAG_CLOCK_DELAY
//上升沿送出TDI数据
SET_TCK
//读取TDO数据
chReceiveData |= (READ_TDO << n);
n++;
/*延时部分*/
JTAG_CLOCK_DELAY
}
if (pchInBuffer != NULL)
{
*pchInBuffer = chReceiveData; //保存收到的数据
}
} >>模块功能:发送JTAG指令
/***********************************************************
* 函数说明:发送指定的JTAG指令 *
* 输入: 指令类型,要发送的指令,保存结果的地址 *
* 输出: 无 *
* 调用函数:JTAG_Shift_Instruction *
***********************************************************/
void JTAG_Shift_Instruction_REG
(
UINT8 chInstructionType,
UINT8 chInstruction,
UINT8 *pchResult
)
{
JTAG_TAP_SHIFT_IR
{
/* 发送指令 */
JTAG_Shift_Data
(
&chInstruction,
pchResult,
chInstructionType,
TRUE
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
}
>>模块功能:发送数据
/***********************************************************
* 函数说明:发送指定位数的数据到数据寄存器 *
* 输入: 类型(数据位数)、保存数据的缓冲,保存结果 *
* 的缓冲 *
* 输出: 无 *
* 调用函数:JTAG_Shift_Instruction *
***********************************************************/
void JTAG_Shift_Data_REG
(
UINT8 chInstructionType,
UINT8 *pchInstruction,
UINT8 *pchResult
)
{
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
pchInstruction,
pchResult,
chInstructionType,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
} >>AVR32 专有JTAG指令:向指定的地址读写一个4字节数据
/***********************************************************
* 函数说明:写存储器函数 *
* 输入: 地址,输出数据缓冲,输入数据缓冲,读写标志 *
* 输出: 写指令是否成功 *
* 调用函数:JTAG_Shift_Data()JTAG_Shift_BigEnding_Data() *
***********************************************************/
BOOL JTAG_Memory_Word_Access
(
BYTE *pchAddress,
UINT32 *pdwOutBuffer,
UINT32 *pdwInBuffer,
BOOL bIfRead
)
{
if (pchAddress == NULL)
{
return FALSE;
}
/*---------------------------------------------------------*
* There is a bug in the jtag implementation. scan in the *
* instruction twice. e.g. *
* select-ir *
* scan MEMORY_WORD_ACCESS bits *
* select-ir *
* scan MEMORY_WORD_ACCESS bits *
* check busy/error bits. *
*---------------------------------------------------------*/
/* 写入指令 */
JTAG_TAP_SHIFT_IR
{
BYTE chTempData = JTAG_MEMROY_WORD_ACCESS;
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
/* 确认系统就绪 */
{
BYTE chTempData = JTAG_MEMROY_WORD_ACCESS;
do
{
JTAG_TAP_SHIFT_IR
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chTempData & BIT(4))
{
//if (chTempData & BIT(4))
//{
SET_PROTECT_FLAG
//}
return FALSE;
}
}
while(chTempData & BIT(2)); /*检测BUSY标志*/
}
/* 写入地址 */
JTAG_TAP_SHIFT_DR
{
/* 发送读写控制信号 */
CLR_TMS
CLR_TCK
if (bIfRead)
{
SET_TDI
}
else
{
CLR_TDI
}
SET_TCK
/* 发送地址数据 */
JTAG_Shift_BigEnding_Data
(
pchAddress,
NULL,
36,
2
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
/*写入数据*/
if (bIfRead)
{
UINT8 chDataBuffer = {0};
if (pdwInBuffer == NULL)
{
return FALSE;
}
/* 读取数据 */
do
{
if (pdwOutBuffer != NULL)
{
TYPE_CONVERSION(&chDataBuffer,UINT32) = *pdwOutBuffer;
}
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
chDataBuffer,
chDataBuffer,
35,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chDataBuffer & BIT(1))
{
SET_ERROR_FLAG
return FALSE;
}
}
while(chDataBuffer & BIT(0)); /*确认写数据成功*/
/* 导出读取到的数据 */
(*pdwInBuffer) = TYPE_CONVERSION(&chDataBuffer,UINT32);
}
else
{
UINT8 chDataBuffer = {0};
BYTE *pchData = NULL;
if (pdwOutBuffer == NULL)
{
return FALSE;
}
if (pdwInBuffer == NULL)
{
pchData = chDataBuffer;
}
else
{
pchData = (BYTE *)pdwInBuffer;
}
/* 写入数据 */
do
{
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
(BYTE *)pdwOutBuffer,
pchData,
32,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
/*
No error can occur between scanning a write
address and the following write data.
if (pchData & BIT(1))
{
SET_ERROR_FLAG
return FALSE;
}
*/
}
while(pchData & BIT(0)); /*确认写数据成功*/
/* 确认系统就绪 */
{
BYTE chTempData = JTAG_MEMROY_WORD_ACCESS;
do
{
JTAG_TAP_SHIFT_IR
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chTempData & BIT(4))
{
//if (chTempData & BIT(4))
//{
SET_PROTECT_FLAG
//}
return FALSE;
}
}
while(chTempData & BIT(2));
}
}
return TRUE;
} >>AVR32 专有JTAG指令:向存储器连续读写数据
/***********************************************************
* 函数说明:块操作函数 *
* 输入: 操作状态,输入数据,输出数据 *
* 输出: 指令是否成功 *
* 调用函数:JTAG_Shift_Data()JTAG_Shift_BigEnding_Data() *
***********************************************************/
BOOL JTAG_Memory_Block_Access
(
UINT8 chStatus,
UINT32 *pdwOutBuffer,
UINT32 *pdwInBuffer
)
{
switch (chStatus)
{
case JTAG_MEM_BLK_SET_COMMAND:
/* 确认系统就绪 */
/* 可靠性代码,其实可以不要
{
BYTE chTempData = JTAG_MEMROY_WORD_ACCESS;
JTAG_TAP_SHIFT_IR
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
JTAG_TAP_RETURN_RUN_TEST_IDEL
do
{
JTAG_TAP_SHIFT_IR
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3
TRUE
);
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chTempData & BIT(4))
{
if (chTempData & BIT(4))
{
SET_PROTECT_FLAG
}
return FALSE;
}
}
while(chTempData & BIT(2));
}
*/
/* 写入指令 */
JTAG_TAP_SHIFT_IR
{
BYTE chTempData = JTAG_MEMROY_BLOCK_ACCESS;
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
break;
case JTAG_MEM_BLK_READ_DATA:
{
UINT8 chDataBuffer = {0};
if (pdwInBuffer == NULL)
{
return FALSE;
}
/* 读取数据 */
do
{
if (pdwOutBuffer != NULL)
{
TYPE_CONVERSION(&chDataBuffer,UINT32) = *pdwOutBuffer;
}
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
chDataBuffer,
chDataBuffer,
34,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
/* 数据的读取操作失败 */
if (chDataBuffer & BIT(1))
{
SET_ERROR_FLAG
return FALSE;
}
}
while(chDataBuffer & BIT(0));
/* 导出读取到的数据 */
(*pdwInBuffer) = TYPE_CONVERSION(&chDataBuffer,UINT32);
}
break;
case JTAG_MEM_BLK_WRITE_DATA:
{
UINT8 chDataBuffer = {0};
BYTE *pchData = chDataBuffer;
if (pdwOutBuffer == NULL)
{
return FALSE;
}
/* 写入数据 */
do
{
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
(BYTE *)pdwOutBuffer,
pchData,
32,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (pchData & BIT(1))
{
SET_ERROR_FLAG
return FALSE;
}
}
while(pchData & BIT(0)); /*确认写数据成功*/
}
break;
default:
return FALSE;
break;
}
return TRUE;
} >>AVR32 专有JTAG指令:AVR_RESET指令
/***********************************************************
* 函数说明:JTAG RESET指令 *
* 输入: 需要操作的数据 *
* 输出: 操作是否成功 *
* 调用函数:JTAG_Shift_Data() *
***********************************************************/
BOOL JTAG_Reset(UINT8 chData)
{
JTAG_TAP_SHIFT_IR
{
BYTE chTempData = JTAG_RESET;
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_Data
(
&chData,
&chData,
JTAG_INS_TYPE_UC3,
FALSE
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
return TRUE;
} 谢谢。强悍的资料啊 :) 支持 顶你个 今天,修改了代码,增加了对JTAG菊花链(《深入浅出AVR单片机》中提到的SPI环路连接)的支持。
牵涉到一些关键的结构和宏:
/********************
*用户变量类型定义 *
********************/
typedef struct DaisyChain DAISY_CHAIN;
/********************
* 结构体定义区 *
********************/
#ifndef __ICCAVR__
#pragma pack(1)
#endif
struct DaisyChain
{
BYTE chUnitsBefore;
BYTE chUnitsAfter;
BYTE chBitsBefore;
BYTE chBitsAfter;
};
#ifndef __ICCAVR__
#pragma pack()
#endif
DAISY_CHAIN g_DaisyChain = {0,0,0,0};
# define SHIFT_DAISY_CHAIN_UNIT(__UNIT_COUNT) \
if ((__UNIT_COUNT))\
{\
UINT8 chUnitCount = (__UNIT_COUNT);\
SET_TCK;\
SET_TDI;\
while(chUnitCount--)\
{\
CLR_TCK;\
NOP();\
SET_TCK;\
}\
}
# define SHIFT_DAISY_CHAIN_BIT(__BIT_COUNT) \
SHIFT_DAISY_CHAIN_UNIT(__BIT_COUNT)
相关代码,我已经更新到对应的位置 >>AVR32 专有JTAG指令:NEXUS指令——用于访问OCD寄存器
/***********************************************************
* 函数说明:AVR32 OCD寄存器访问指令 *
* 输入: OCD寄存器编号,输入输出缓冲指针,读写控制*
* 输出: 操作是否成功 *
* 调用函数:JTAG_Shift_Data() JTAG_Shift_BigEnding_Data*
***********************************************************/
BOOL JTAG_Nexus
(
BYTE chREGIndex,
UINT32 *pdwOutBuffer,
UINT32 *pdwInBuffer,
BOOL bIfRead
)
{
/* 检测系统是否忙 */
{
BYTE chTempData = JTAG_NEXUS;
do
{
JTAG_TAP_SHIFT_IR
JTAG_Shift_Data
(
&chTempData,
&chTempData,
JTAG_INS_TYPE_UC3,
TRUE
);
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chTempData & BIT(4))
{
SET_PROTECT_FLAG
return FALSE;
}
}
while(chTempData & BIT(2));
}
/* 写入地址 */
JTAG_TAP_SHIFT_DR
{
/* 发送读写控制信号 */
CLR_TMS
CLR_TCK
if (bIfRead)
{
SET_TDI
}
else
{
CLR_TDI
}
SET_TCK
/* 发送地址数据 */
JTAG_Shift_BigEnding_Data
(
&chREGIndex,
NULL,
7,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
/*写入数据*/
if (bIfRead)
{
UINT8 chDataBuffer = {0};
if (pdwInBuffer == NULL)
{
return FALSE;
}
/* 读取数据 */
do
{
if (pdwOutBuffer != NULL)
{
TYPE_CONVERSION(&chDataBuffer,UINT32) = *pdwOutBuffer;
}
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
chDataBuffer,
chDataBuffer,
34,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chDataBuffer & BIT(1))
{
SET_ERROR_FLAG
return FALSE;
}
}
while(chDataBuffer & BIT(0)); /*确认写数据成功*/
/* 导出读取到的数据 */
(*pdwInBuffer) = TYPE_CONVERSION(&chDataBuffer,UINT32);
}
else
{
UINT8 chDataBuffer = {0};
BYTE *pchData = NULL;
if (pdwOutBuffer == NULL)
{
return FALSE;
}
if (pdwInBuffer == NULL)
{
pchData = chDataBuffer;
}
else
{
pchData = (BYTE *)pdwInBuffer;
}
/* 写入数据 */
do
{
JTAG_TAP_SHIFT_DR
{
JTAG_Shift_BigEnding_Data
(
(BYTE *)pdwOutBuffer,
pchData,
32,
0
);
}
JTAG_TAP_RETURN_RUN_TEST_IDEL
/*
No error can occur between scanning a write
address and the following write data.
if (pchData & BIT(1))
{
SET_ERROR_FLAG
return FALSE;
}
*/
}
while(pchData & BIT(0)); /*确认写数据成功*/
/* 确认系统就绪 */
{
BYTE chTempData = JTAG_MEMROY_WORD_ACCESS;
do
{
JTAG_TAP_SHIFT_IR
JTAG_Shift_Data(&chTempData,&chTempData,JTAG_INS_TYPE_UC3);
JTAG_TAP_RETURN_RUN_TEST_IDEL
if (chTempData & BIT(4))
{
SET_PROTECT_FLAG
return FALSE;
}
}
while(chTempData & BIT(2));
}
}
return TRUE;
} 学习 希望我能看懂!支持! 学习 收藏,谢谢 多谢傻孩子。。。 感谢傻孩子分享!
页:
[1]