Files
player/Project_App_Calendar/App_Src/drive/swd.c
2025-07-05 19:47:28 +08:00

631 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}