Files
player/Project_App_Chat/App_Src/drive/swd.c

631 lines
11 KiB
C
Raw Normal View History

2025-06-27 00:32:57 +08:00
#include "stm32f4xx.h"
#include "base.h"
#include "swd.h"
//时钟PA4数据PA5
#define SWD_CLK PAout(4)
#define SWD_DIO_OUT PAout(5)
#define SWD_DIO_IN PAin(5)
//用寄存器方式设置为上拉输入模式
#define SWD_DIN() {GPIOA->MODER&=~(3<<(5*2));}
//用寄存器方式设置为推挽输出模式
#define SWD_DOUT() {GPIOA->MODER|=(1<<(5*2));}
//#define SWD_DELAY() {int time=10;while(time--);}
#define SWD_DELAY() {}
void SWD_Init (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//使用GPIO来模拟SWD接口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //速度选择
GPIO_Init(GPIOA, &GPIO_InitStructure);
SWD_CLK=0;
SWD_DIO_OUT=1;
}
#if 1
//低位在前,高位在后
//上升沿刷新,下降沿锁存
void SWD_SendByte (u8 byte)
{
SWD_DOUT();
for (u8 i=0;i<8;i++)
{
SWD_DIO_OUT=byte>>i;
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
}
u8 SWD_RecvByte (void)
{
u8 byte=0;
SWD_DIN();
for (u8 i=0;i<8;i++)
{
byte>>=1;
byte|=(SWD_DIO_IN<<7);
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
return byte;
}
void SWD_Turn (void)
{
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
u8 SWD_Ask (void)
{
u8 ask=0;
SWD_DIN();
for (u8 i=0;i<3;i++)
{
ask>>=1;
ask|=(SWD_DIO_IN<<2);
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
return ask;
}
u8 SWD_Praity (void)
{
u8 par=0;
SWD_DIN();
par=SWD_DIO_IN;
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
return par;
}
void SWD_SendPraity (u8 pra)
{
SWD_DOUT();
SWD_DIO_OUT=pra;
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
u32 SWD_ReadReg (u8 cmd,u8 *err)
{
cmd|=0x81|SWD_READ;
u8 _1num=0;
for (u8 i=0;i<4;i++)
{
if (cmd&(1<<(i+1)))
{
_1num++;
}
}
if (_1num%2) cmd|=1<<5;
u8 ask=0;
int time_out=100;
do
{
SWD_SendByte(cmd);
SWD_Turn();
ask=SWD_Ask();
}while ((ask!=SWD_ERR_OK)&&time_out--);
*err=ask;
if (*err!=SWD_ERR_OK)
return (u32)-1;
u32 data=0;
u8 praity=0;
data|=SWD_RecvByte();
data|=SWD_RecvByte()<<8;
data|=SWD_RecvByte()<<16;
data|=SWD_RecvByte()<<24;
praity=SWD_Praity();
SWD_SendByte(0);
//SWD_Turn();
_1num=0;
for (u8 i=0;i<32;i++)
{
if (data&(1<<i))
{
_1num++;
}
}
//delay_us(170);
if ((_1num%2)==(praity&1))//校验成功
{
return data;
}
else
{
*err=0x07;
return 0;
}
}
void SWD_WriteReg (u8 cmd,u8 *err,u32 data)
{
cmd|=0x81|SWD_WRITE;
u8 _1num=0;
for (u8 i=0;i<4;i++)
{
if (cmd&(1<<(i+1)))
{
_1num++;
}
}
if (_1num%2) cmd|=1<<5;
u8 ask=0;
int time_out=100;
do
{
SWD_SendByte(cmd);
SWD_Turn();
ask=SWD_Ask();
SWD_Turn();
}while ((ask!=SWD_ERR_OK)&&time_out--);
*err=ask;
if (*err!=SWD_ERR_OK)
return ;
_1num=0;
for (u8 i=0;i<32;i++)
{
if (data&(1<<i))
{
_1num++;
}
}
SWD_SendByte(data&0xff);
SWD_SendByte(data>>8);
SWD_SendByte(data>>16);
SWD_SendByte(data>>24);
//SWD_SendPraity(_1num%2);
SWD_SendByte(_1num%2);
//delay_us(170);
}
#else
//低位在前,高位在后
//上升沿刷新,下降沿锁存
void SWD_SendByte (u8 byte)
{
SWD_DOUT();
for (u8 i=0;i<8;i++)
{
SWD_DIO_OUT=byte>>i;
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
}
//接受1字节数据下降沿锁存
u8 SWD_RecvByte (void)
{
u8 byte=0;
SWD_DIN();
for (u8 i=0;i<8;i++)
{
byte>>=1;
byte|=(SWD_DIO_IN<<7);
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
return byte;
}
void SWD_Turn (void)
{
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
//接受回应,下降沿锁存
u8 SWD_Ask (void)
{
u8 ask=0;
SWD_DIN();
for (u8 i=0;i<3;i++)
{
ask>>=1;
ask|=(SWD_DIO_IN<<2);
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
return ask;
}
//接受校验位,下降沿锁存
u8 SWD_Praity (void)
{
u8 par=0;
SWD_DIN();
par=SWD_DIO_IN;
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
return par;
}
void SWD_SendPraity (u8 pra)
{
SWD_DOUT();
SWD_DIO_OUT=pra;
SWD_CLK=1;
SWD_DELAY();
SWD_CLK=0;
SWD_DELAY();
}
u32 SWD_ReadReg (u8 cmd,u8 *err)
{
cmd|=0x81|SWD_READ;
u8 _1num=0;
for (u8 i=0;i<4;i++)
{
if (cmd&(1<<(i+1)))
{
_1num++;
}
}
if (_1num%2) cmd|=1<<5;
do{
u8 ask=0;
int time_out=10000;
do
{
SWD_SendByte(cmd);
SWD_Turn();
ask=SWD_Ask();
if (ask==SWD_ERR_OTHER) SWD_LineReset();
}while ((ask!=SWD_ERR_OK)&&time_out--);
*err=ask;
if (*err!=SWD_ERR_OK)
return (u32)-1;
u32 data=0;
u8 praity=0;
data|=SWD_RecvByte();
data|=SWD_RecvByte()<<8;
data|=SWD_RecvByte()<<16;
data|=SWD_RecvByte()<<24;
praity=SWD_Praity();
SWD_SendByte(0);
//SWD_Turn();
u8 _1num2=0;
for (u8 i=0;i<32;i++)
{
if (data&(1<<i))
{
_1num2++;
}
}
if ((_1num2%2)==(praity&1))//校验成功
{
return data;
}
else
{
*err=0x07;
//return 0;
}
}while (*err!=SWD_ERR_OK);
return 0;
}
void SWD_WriteReg (u8 cmd,u8 *err,u32 data)
{
cmd|=0x81|SWD_WRITE;
u8 _1num=0;
for (u8 i=0;i<4;i++)
{
if (cmd&(1<<(i+1)))
{
_1num++;
}
}
if (_1num%2) cmd|=1<<5;
do{
u8 ask=0;
int time_out=10000;
do
{
SWD_SendByte(cmd);
SWD_Turn();
ask=SWD_Ask();
SWD_Turn();
if (ask==SWD_ERR_OTHER) SWD_LineReset();
}while ((ask!=SWD_ERR_OK)&&time_out--);
*err=ask;
if (*err!=SWD_ERR_OK)
return ;
u8 _1num2=0;
for (u8 i=0;i<32;i++)
{
if (data&(1<<i))
{
_1num2++;
}
}
SWD_SendByte(data&0xff);
SWD_SendByte(data>>8);
SWD_SendByte(data>>16);
SWD_SendByte(data>>24);
SWD_SendByte(_1num2%2);
}while (*err!=SWD_ERR_OK);
}
#endif
void SWD_LineReset (void)
{
for (u8 i=0;i<7;i++)
{
SWD_SendByte(0xff);
}
SWD_SendByte(0x9e);//低字节在前
SWD_SendByte(0xe7);
for (u8 i=0;i<7;i++)
{
SWD_SendByte(0xff);
}
SWD_SendByte(0xb6);//低字节在前
SWD_SendByte(0xed);
for (u8 i=0;i<7;i++)
{
SWD_SendByte(0xff);
}
SWD_SendByte(0x00);//低字节在前
SWD_SendByte(0x00);
}
//向内存写入数据,成功返回设备id
u32 SWD_WriteSram (u32 addr,u32 *data,u32 len)
{
u8 err=0;
u32 id=0;
//SWD_LineReset();
id=SWD_ReadReg(SWD_REG_DP|SWD_REG_IDCODE,&err);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_ABORT,&err,0x1e);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_CTRL_STAT,&err,0x50000000);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_SELECT,&err,0x00);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_CSW,&err,0x23000012);//地址自动递增
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,addr);//在这个地址的内存空间写数据
if (err!=SWD_ERR_OK) return 0;
while (len--)
{
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,*data);
if (err!=SWD_ERR_OK) return 0;
data++;
}
return id;
}
//向内存读取数据,成功返回设备id
u32 SWD_ReadSram (u32 addr,u32 *data,u32 len)
{
u8 err=0;
u32 id=0;
//SWD_LineReset();
id=SWD_ReadReg(SWD_REG_DP|SWD_REG_IDCODE,&err);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_ABORT,&err,0x1e);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_CTRL_STAT,&err,0x50000000);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_SELECT,&err,0x00);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_CSW,&err,0x23000012);//地址自动递增
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,addr);//在这个地址的内存空间数据
if (err!=SWD_ERR_OK) return 0;
*data=SWD_ReadReg(SWD_REG_AP|SWD_REG_DRW,&err);//读取一次无效数据
if (err!=SWD_ERR_OK) return 0;
while (len--)
{
*data=SWD_ReadReg(SWD_REG_AP|SWD_REG_DRW,&err);
if (err!=SWD_ERR_OK) return 0;
data++;
}
return id;
}
//暂停或者启动内核1暂停0启动
u32 SWD_Cm3Halt (u8 value)
{
u8 err=0;
u32 id=0;
//SWD_LineReset();
id=SWD_ReadReg(SWD_REG_DP|SWD_REG_IDCODE,&err);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_ABORT,&err,0x1e);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_CTRL_STAT,&err,0x50000000);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_SELECT,&err,0x00);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_CSW,&err,0x23000002);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_DHCSR);//暂停CM3内核
if (err!=SWD_ERR_OK) return 0;
if (value)
{
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,0xa05f0001);//写入钥匙,使能调试
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_DEMCR);//使能复位后停止
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,0x1);//
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_AIRCR);//复位
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,0x05fa0004);//
if (err!=SWD_ERR_OK) return 0;
}
else
{
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,0xa05f0000);//写入钥匙,使能调试
if (err!=SWD_ERR_OK) return 0;
// SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_DEMCR);//使能复位后停止
// if (err!=SWD_ERR_OK) return 0;
// SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,0x0);//
// if (err!=SWD_ERR_OK) return 0;
// SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_AIRCR);//复位
// if (err!=SWD_ERR_OK) return 0;
// SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,0x05fa0004);//
// if (err!=SWD_ERR_OK) return 0;
}
return id;
}
//向内核寄存器写入数据
u32 SWD_WriteCm3Reg (u16 reg_select,u32 data)
{
u8 err=0;
u32 id=0;
//SWD_LineReset();
id=SWD_ReadReg(SWD_REG_DP|SWD_REG_IDCODE,&err);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_ABORT,&err,0x1e);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_CTRL_STAT,&err,0x50000000);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_DP|SWD_REG_SELECT,&err,0x00);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_CSW,&err,0x23000002);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_DCRDR);//内核数据寄存器
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,data);
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_DCRSR);//选择内核寄存器
if (err!=SWD_ERR_OK) return 0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_DRW,&err,reg_select|CM3_REG_WRITE);
if (err!=SWD_ERR_OK) return 0;
u32 dhcsr_data=0;
SWD_WriteReg(SWD_REG_AP|SWD_REG_TAR,&err,CM3_DHCSR);//
if (err!=SWD_ERR_OK) return 0;
dhcsr_data=SWD_ReadReg(SWD_REG_AP|SWD_REG_DRW,&err);
if (err!=SWD_ERR_OK) return 0;
do
{
dhcsr_data=SWD_ReadReg(SWD_REG_AP|SWD_REG_DRW,&err);
if (err!=SWD_ERR_OK) return 0;
}while ((dhcsr_data&0x00010000)==0);
return id;
}