过IO模拟SWD协议,读写cortex M0+ 的寄存器源码。
自己从0开始撸出来的,实测可用。
移植时,实现IO操作的几个宏就能工作了!
源码如下:
//==============================================================================
//SWDIO = PA1
#define SWDIO_SetHigh() ( M0P_GPIOA->BSRR = 1<<1 )
#define SWDIO_SetLow() ( M0P_GPIOA->BRR = 1<<1 )
#define SWDIO_SetInput() ( M0P_GPIOA->DIR_f.PIN1 = 1 )
#define SWDIO_SetOutput() ( M0P_GPIOA->DIR_f.PIN1 = 0 )
#define SWDIO_GetValue() ( M0P_GPIOA->IN & (1<<1) )
//SWCLK = PA2
#define SWCLK_SetHigh() ( M0P_GPIOA->BSRR = 1<<2 )
#define SWCLK_SetLow() ( M0P_GPIOA->BRR = 1<<2 )
#define SWCLK_SetOutput() ( M0P_GPIOA->DIR_f.PIN2 = 0 )
//==============================================================================
#define SwdDly() __nop();__nop();
//==============================================================================
int main(void)
{
__IO uint8_t tmp8;
__IO uint32_t tmp32;
M0P_SYSCTRL->PERICLKEN0 = 0xffffffff;
M0P_SYSCTRL->PERICLKEN1 = 0xffffffff;
M0P_GPIOA->ADS = 0x00;
Swd_Bus_Reset();
while( 1 )
{
// Swd_Bus_Reset();
//
// Swd_Bus_SendByte( 0x9E );
// Swd_Bus_SendByte( 0xE7 );
// Swd_Bus_SendByte( 0x00 );
// Swd_Bus_SendByte( 0x00 );
//
Swd_Bus_Reset();
Swd_Bus_SendByte( 0x00 );
//--------------------------------------------------
//Read DP.IDR
Swd_Bus_SendByte( 0xa5 );
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity();
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
//--------------------------------------------------
//write ctrl/state
Swd_Bus_SendByte( 0xa9 );
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0x50000000 );
Swd_Bus_SendByte( 0x00 );
//--------------------------------------------------
//Read AP.IDR
Swd_Bus_SendByte( 0xb1 ); //write select AP BANK - 0F
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0x000000f0 );
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0x9f ); //read DRW dummy
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity();
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0xbd ); //read rdbuf
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity();
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
//--------------------------------------------------
//SET AP 位宽为32位
Swd_Bus_SendByte( 0xb1 ); //write select AP BANK - 00
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0x00000000 );
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0xA3 ); //write CSW -
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0x23000002 ); //32bit 位宽,地址不自动增加
Swd_Bus_SendByte( 0x00 );
//--------------------------------------------------
//stop the cpu
Swd_Bus_SendByte( 0x8B ); //write TAR
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0xE000EDF0 ); //
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0xBB ); //WRITE DRW
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0xA05F0303 );
Swd_Bus_SendByte( 0x00 );
//--------------------------------------------------
//Read User Memery [url=home.php?mod=space&uid=72445]@[/url] 0x00100d90
Swd_Bus_SendByte( 0x8B ); //write TAR
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0x00100d90 );
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0x9f ); //read DRW
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity(); //dummy
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0xbd ); //read rdbuf
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity(); //read
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
//--------------------------------
//write and read reg [url=home.php?mod=space&uid=72445]@[/url] 0x40020F04
Swd_Bus_SendByte( 0x8B ); //write TAR
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0x40020F04 );
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0xBB ); //WRITE DRW
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
Swd_Bus_Turn();
Swd_Bus_SendWordAndParity( 0xffffffff );
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0x9f ); //read DRW dummy
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity();
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
Swd_Bus_SendByte( 0xbd ); //read rdbuf
Swd_Bus_Turn();
tmp8 = Swd_Bus_RecvAck();
tmp32 = Swd_Bus_RecvWordAndParity();
Swd_Bus_Turn();
Swd_Bus_SendByte( 0x00 );
while( 1 );
}
}
//==============================================================================
void Swd_Bus_Reset( void )
{
uint8_t i;
SWCLK_SetOutput();
SWDIO_SetOutput();
SWDIO_SetHigh();
SWCLK_SetLow();
for( i=0; i<56; i++ )
{
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
SwdDly();
}
}
void Swd_Bus_Turn( void )
{
SWDIO_SetInput();
SwdDly();
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
SwdDly();
}
//LSB FIRST
void Swd_Bus_SendByte( uint8_t Va )
{
uint8_t i;
SWDIO_SetLow();
SWDIO_SetOutput();
for( i=0; i<8; i++ )
{
if( Va & 0x01 )
{
SWDIO_SetHigh();
}
else
{
SWDIO_SetLow();
}
Va >>= 1;
SwdDly();
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
}
SwdDly();
}
//LSB FIRST
void Swd_Bus_SendWordAndParity( uint32_t Va )
{
uint8_t i;
uint8_t Pa = 0x00;
SWDIO_SetLow();
SWDIO_SetOutput();
for( i=0; i<32; i++ )
{
if( Va & 0x01 )
{
SWDIO_SetHigh();
Pa++;
}
else
{
SWDIO_SetLow();
}
Va >>= 1;
SwdDly();
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
}
//send Parity
if( Pa & 0x01 )
{
SWDIO_SetHigh();
}
else
{
SWDIO_SetLow();
}
SwdDly();
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
SwdDly();
}
//LSB FIRST
uint32_t Swd_Bus_RecvWordAndParity( void )
{
uint8_t i;
uint32_t tmp32;
tmp32 = 0x00;
SWDIO_SetInput();
SwdDly();
for( i=0; i<32; i++ )
{
if( SWDIO_GetValue() )
{
tmp32 >>= 1;
tmp32 |= bv31;
}
else
{
tmp32 >>= 1;
}
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
SwdDly();
}
//------------------------------
//Parity
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
SwdDly();
return( tmp32 );
}
//LSB FIRST
uint8_t Swd_Bus_RecvAck( void )
{
uint8_t i;
uint8_t tmp8;
tmp8 = 0x00;
SWDIO_SetInput();
SwdDly();
for( i=0; i<3; i++ )
{
if( SWDIO_GetValue() )
{
tmp8 >>= 1;
tmp8 |= bv2;
}
else
{
tmp8 >>= 1;
}
SWCLK_SetHigh();
SwdDly();
SWCLK_SetLow();
SwdDly();
}
return( tmp8 );
}