446 lines
12 KiB
C
446 lines
12 KiB
C
/*
|
|
******************************************************************************
|
|
* @file SWD.c
|
|
* @author FreqChip Firmware Team
|
|
* @version V1.0.0
|
|
* @date 2023
|
|
* @brief SWD module Demo.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* Copyright (c) 2023 FreqChip.
|
|
* All rights reserved.
|
|
******************************************************************************
|
|
*/
|
|
#include "co_util.h"
|
|
|
|
#include "fr30xx.h"
|
|
|
|
#include "SWD.h"
|
|
|
|
#define PMU_SWD_IE 0x43
|
|
#define PMU_SWD_DATA 0x49
|
|
#define PMU_SWD_DIR 0x4b
|
|
#define PMU_SWD_IOMUX 0x5b
|
|
#define PMU_SWD_PULL_EN 0x45
|
|
#define PMU_SWD_PULL_SEL 0x47
|
|
//#define PMU_SWD_IE 0x42
|
|
//#define PMU_SWD_DATA 0x48
|
|
//#define PMU_SWD_DIR 0x4a
|
|
//#define PMU_SWD_IOMUX 0x59
|
|
|
|
#define SWD_CLK_H 0x01
|
|
#define SWD_CLK_L 0x02
|
|
#define SWD_DATA_H 0x02
|
|
#define SWD_DATA_L 0x01
|
|
|
|
static uint8_t SWD_DATA,SWD_CLK;
|
|
|
|
#define ool_write_ram(addr, data) frspim_wr_ram(FR_SPI_PMU_CHAN,(addr),1, (data))
|
|
#define ool_read_ram(addr) (uint8_t)frspim_rd_ram(FR_SPI_PMU_CHAN,(addr),1)
|
|
|
|
/*---------------------------------- Porting ----------------------------------------*/
|
|
|
|
#define RAM_CODE __RAM_CODE
|
|
|
|
|
|
#define SWD_CLK_SET_H() {SWD_CLK = SWD_CLK_H; \
|
|
ool_write_ram(PMU_SWD_DATA,SWD_DATA | SWD_CLK);}
|
|
#define SWD_CLK_SET_L() {SWD_CLK = SWD_CLK_L; \
|
|
ool_write_ram(PMU_SWD_DATA,SWD_DATA & SWD_CLK);}
|
|
|
|
#define SWD_IO_SET_H() {SWD_DATA = SWD_DATA_H; \
|
|
ool_write_ram(PMU_SWD_DATA,SWD_CLK | SWD_DATA);}
|
|
#define SWD_IO_SET_L() {SWD_DATA = SWD_DATA_L; \
|
|
ool_write_ram(PMU_SWD_DATA,SWD_CLK & SWD_DATA);}
|
|
#define SWD_IO_IN() (ool_read_ram(PMU_SWD_DATA) & 0x02)
|
|
|
|
#define SWD_IO_OUT_ENABLE() (ool_write_ram(PMU_SWD_DIR,0x00))
|
|
#define SWD_IO_OUT_DISABLE() (ool_write_ram(PMU_SWD_DIR,0x02))
|
|
|
|
void SWD_IO_init(void)
|
|
{
|
|
ool_write_ram(PMU_SWD_PULL_EN, 0x03);
|
|
ool_write_ram(PMU_SWD_PULL_SEL, 0x00);
|
|
ool_write_ram(PMU_SWD_IE, 0x03);
|
|
ool_write_ram(PMU_SWD_DIR, 0x00);
|
|
ool_write_ram(PMU_SWD_DATA, 0x03);
|
|
ool_write_ram(PMU_SWD_IOMUX, 0x00);
|
|
|
|
SWD_CLK_SET_L();
|
|
SWD_IO_SET_L();
|
|
}
|
|
/*---------------------------------- Porting end ----------------------------------------*/
|
|
|
|
|
|
#define SW_CLOCK_CYCLE() \
|
|
SWD_CLK_SET_H(); \
|
|
SWD_DELAY(); \
|
|
SWD_CLK_SET_L(); \
|
|
SWD_DELAY()
|
|
|
|
#define SW_WRITE_BIT_0() \
|
|
SWD_IO_SET_L(); \
|
|
SWD_DELAY(); \
|
|
SWD_DELAY(); \
|
|
SWD_CLK_SET_H(); \
|
|
SWD_DELAY(); \
|
|
SWD_DELAY(); \
|
|
SWD_CLK_SET_L()
|
|
|
|
#define SW_WRITE_BIT_1() \
|
|
SWD_IO_SET_H(); \
|
|
SWD_DELAY(); \
|
|
SWD_DELAY(); \
|
|
SWD_CLK_SET_H(); \
|
|
SWD_DELAY(); \
|
|
SWD_DELAY(); \
|
|
SWD_CLK_SET_L()
|
|
|
|
|
|
#define SW_READ_BIT(BIT) \
|
|
SWD_CLK_SET_H(); \
|
|
SWD_DELAY(); \
|
|
SWD_DELAY(); \
|
|
SWD_CLK_SET_L(); \
|
|
SWD_DELAY(); \
|
|
SWD_DELAY(); \
|
|
BIT = SWD_IO_IN()
|
|
|
|
|
|
RAM_CODE static inline void SW_WRITE_BIT(uint32_t BIT)
|
|
{
|
|
switch (BIT)
|
|
{
|
|
case 0:
|
|
{
|
|
SW_WRITE_BIT_0();
|
|
}break;
|
|
|
|
case 1:
|
|
{
|
|
SW_WRITE_BIT_1();
|
|
}break;
|
|
|
|
default:break;
|
|
}
|
|
}
|
|
|
|
RAM_CODE int SWD_TransferFunction(uint32_t request, uint32_t *data, uint32_t Trailing)
|
|
{
|
|
int i;
|
|
uint32_t W_Parity;
|
|
|
|
uint32_t ACK;
|
|
bool BitBuffer[33];
|
|
bool ACKBuffer[3];
|
|
|
|
bool APnDP = (request >> 0) & 1;
|
|
bool RnW = (request >> 1) & 1;
|
|
bool A2 = (request >> 2) & 1;
|
|
bool A3 = (request >> 3) & 1;
|
|
bool parity = (APnDP + RnW + A2 + A3) & 0x01;
|
|
|
|
if (RnW == 0)
|
|
{
|
|
/* Prepare data */
|
|
W_Parity = 0;
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
BitBuffer[i] = (*data >> i) & 1;
|
|
W_Parity += BitBuffer[i];
|
|
}
|
|
|
|
W_Parity &= 0x01;
|
|
BitBuffer[32] = W_Parity;
|
|
}
|
|
|
|
SWD_IO_OUT_ENABLE();
|
|
/* Packet Request */
|
|
SW_WRITE_BIT(1U); /* Start Bit */
|
|
SW_WRITE_BIT(APnDP); /* APnDP Bit */
|
|
SW_WRITE_BIT(RnW); /* RnW Bit */
|
|
SW_WRITE_BIT(A2); /* A2 Bit */
|
|
SW_WRITE_BIT(A3); /* A3 Bit */
|
|
SW_WRITE_BIT(parity); /* parity Bit */
|
|
SW_WRITE_BIT(0U); /* Stop Bit */
|
|
SW_WRITE_BIT(1U); /* Park Bit */
|
|
|
|
/* Turnaround */
|
|
SWD_IO_OUT_DISABLE();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
|
|
SWD_CLK_SET_H();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
|
|
|
|
/* Acknowledge response */
|
|
SW_READ_BIT(ACKBuffer[0]);
|
|
SW_READ_BIT(ACKBuffer[1]);
|
|
SW_READ_BIT(ACKBuffer[2]);
|
|
ACK = (ACKBuffer[0] << 2) | (ACKBuffer[1] << 1) | ACKBuffer[2];
|
|
|
|
/* OK response */
|
|
if (ACK == DAP_TRANSFER_OK)
|
|
{
|
|
/* Data transfer */
|
|
if (RnW == 1)
|
|
{
|
|
/* Read data */
|
|
|
|
/* Read RDATA[0:31] */
|
|
SW_READ_BIT(BitBuffer[0]);
|
|
SW_READ_BIT(BitBuffer[1]);
|
|
SW_READ_BIT(BitBuffer[2]);
|
|
SW_READ_BIT(BitBuffer[3]);
|
|
SW_READ_BIT(BitBuffer[4]);
|
|
SW_READ_BIT(BitBuffer[5]);
|
|
SW_READ_BIT(BitBuffer[6]);
|
|
SW_READ_BIT(BitBuffer[7]);
|
|
SW_READ_BIT(BitBuffer[8]);
|
|
SW_READ_BIT(BitBuffer[9]);
|
|
SW_READ_BIT(BitBuffer[10]);
|
|
SW_READ_BIT(BitBuffer[11]);
|
|
SW_READ_BIT(BitBuffer[12]);
|
|
SW_READ_BIT(BitBuffer[13]);
|
|
SW_READ_BIT(BitBuffer[14]);
|
|
SW_READ_BIT(BitBuffer[15]);
|
|
SW_READ_BIT(BitBuffer[16]);
|
|
SW_READ_BIT(BitBuffer[17]);
|
|
SW_READ_BIT(BitBuffer[18]);
|
|
SW_READ_BIT(BitBuffer[19]);
|
|
SW_READ_BIT(BitBuffer[20]);
|
|
SW_READ_BIT(BitBuffer[21]);
|
|
SW_READ_BIT(BitBuffer[22]);
|
|
SW_READ_BIT(BitBuffer[23]);
|
|
SW_READ_BIT(BitBuffer[24]);
|
|
SW_READ_BIT(BitBuffer[25]);
|
|
SW_READ_BIT(BitBuffer[26]);
|
|
SW_READ_BIT(BitBuffer[27]);
|
|
SW_READ_BIT(BitBuffer[28]);
|
|
SW_READ_BIT(BitBuffer[29]);
|
|
SW_READ_BIT(BitBuffer[30]);
|
|
SW_READ_BIT(BitBuffer[31]);
|
|
|
|
/* Read Parity */
|
|
SW_READ_BIT(BitBuffer[32]);
|
|
|
|
/* Trailing */
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
for (i = 0; i < Trailing; i++)
|
|
{
|
|
SW_CLOCK_CYCLE();
|
|
}
|
|
|
|
*data = 0;
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
*data |= (BitBuffer[i] << i);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Write data */
|
|
|
|
/* Turnaround */
|
|
SWD_CLK_SET_H();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
|
|
SWD_CLK_SET_L();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
|
|
SWD_CLK_SET_H();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
|
|
SWD_CLK_SET_L();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
|
|
|
|
SWD_IO_OUT_ENABLE();
|
|
|
|
/* Write WDATA[0:31] */
|
|
SW_WRITE_BIT(BitBuffer[0]);
|
|
SW_WRITE_BIT(BitBuffer[1]);
|
|
SW_WRITE_BIT(BitBuffer[2]);
|
|
SW_WRITE_BIT(BitBuffer[3]);
|
|
SW_WRITE_BIT(BitBuffer[4]);
|
|
SW_WRITE_BIT(BitBuffer[5]);
|
|
SW_WRITE_BIT(BitBuffer[6]);
|
|
SW_WRITE_BIT(BitBuffer[7]);
|
|
SW_WRITE_BIT(BitBuffer[8]);
|
|
SW_WRITE_BIT(BitBuffer[9]);
|
|
SW_WRITE_BIT(BitBuffer[10]);
|
|
SW_WRITE_BIT(BitBuffer[11]);
|
|
SW_WRITE_BIT(BitBuffer[12]);
|
|
SW_WRITE_BIT(BitBuffer[13]);
|
|
SW_WRITE_BIT(BitBuffer[14]);
|
|
SW_WRITE_BIT(BitBuffer[15]);
|
|
SW_WRITE_BIT(BitBuffer[16]);
|
|
SW_WRITE_BIT(BitBuffer[17]);
|
|
SW_WRITE_BIT(BitBuffer[18]);
|
|
SW_WRITE_BIT(BitBuffer[19]);
|
|
SW_WRITE_BIT(BitBuffer[20]);
|
|
SW_WRITE_BIT(BitBuffer[21]);
|
|
SW_WRITE_BIT(BitBuffer[22]);
|
|
SW_WRITE_BIT(BitBuffer[23]);
|
|
SW_WRITE_BIT(BitBuffer[24]);
|
|
SW_WRITE_BIT(BitBuffer[25]);
|
|
SW_WRITE_BIT(BitBuffer[26]);
|
|
SW_WRITE_BIT(BitBuffer[27]);
|
|
SW_WRITE_BIT(BitBuffer[28]);
|
|
SW_WRITE_BIT(BitBuffer[29]);
|
|
SW_WRITE_BIT(BitBuffer[30]);
|
|
SW_WRITE_BIT(BitBuffer[31]);
|
|
|
|
/* Write Parity Bit */
|
|
SW_WRITE_BIT(BitBuffer[32]);
|
|
|
|
SWD_IO_OUT_DISABLE();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
__NOP();__NOP();__NOP();__NOP();__NOP();
|
|
/* Trailing */
|
|
for (i = 0; i < Trailing; i++)
|
|
{
|
|
SW_CLOCK_CYCLE();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* WAIT or FAULT response */
|
|
if (ACK == DAP_TRANSFER_WAIT)
|
|
{
|
|
SW_CLOCK_CYCLE();
|
|
SW_CLOCK_CYCLE();
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
RAM_CODE void SWD_Line_Reset(uint32_t fu32_CNT)
|
|
{
|
|
int i;
|
|
SWD_IO_OUT_ENABLE();
|
|
|
|
SWD_IO_SET_H();
|
|
for (i = 0; i < fu32_CNT; i++)
|
|
{
|
|
SW_CLOCK_CYCLE();
|
|
}
|
|
SWD_IO_SET_L();
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
SW_CLOCK_CYCLE();
|
|
}
|
|
}
|
|
|
|
RAM_CODE void SWD_Connect(void)
|
|
{
|
|
uint32_t Data;
|
|
|
|
/* Line Reset */
|
|
SWD_Line_Reset(56);
|
|
SWD_Line_Reset(59);
|
|
SWD_Line_Reset(59);
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
SW_CLOCK_CYCLE();
|
|
}
|
|
|
|
/* Read IDCODE */
|
|
SWD_TransferFunction(REQ_DP|REQ_R|REQ_ADDR_0, &Data, 6); co_delay_10us(1);
|
|
}
|
|
|
|
RAM_CODE void SWD_Enable_Debug(void)
|
|
{
|
|
uint32_t Data;
|
|
|
|
/* Write Abort */
|
|
Data = 0x0000001E;
|
|
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_0, &Data, 7); co_delay_10us(1);
|
|
/* Write CTRL/STAT */
|
|
Data = 0x50000000;
|
|
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_1, &Data, 7); co_delay_10us(1);
|
|
}
|
|
|
|
RAM_CODE void SWD_W_REG(uint32_t ADDR, uint32_t Value)
|
|
{
|
|
uint32_t Data;
|
|
/* Write Abort */
|
|
Data = 0x0000001E;
|
|
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_0, &Data, 7);
|
|
/* Write Select */
|
|
Data = 0x00000000;
|
|
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_2, &Data, 0);
|
|
/* Write CSW */
|
|
Data = 0x23000012;
|
|
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_0, &Data, 0);
|
|
/* Write TAR */
|
|
Data = ADDR;
|
|
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_1, &Data, 0);
|
|
/* Write DRW */
|
|
Data = Value;
|
|
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_3, &Data, 7);
|
|
/* Read RDBUFF */
|
|
SWD_TransferFunction(REQ_DP|REQ_R|REQ_ADDR_3, &Data, 3);
|
|
}
|
|
|
|
RAM_CODE void SWD_R_REG(uint32_t ADDR, uint32_t *Buffer, uint32_t Length)
|
|
{
|
|
int ERR;int first = 0;
|
|
|
|
uint32_t Data;
|
|
/* Write Abort */
|
|
Data = 0x0000001E;
|
|
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_0, &Data, 7);
|
|
/* Write Select */
|
|
Data = 0x00000000;
|
|
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_2, &Data, 0);
|
|
/* Write CSW */
|
|
Data = 0x23000012;
|
|
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_0, &Data, 0);
|
|
/* Write TAR */
|
|
Data = ADDR;
|
|
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_1, &Data, 0);
|
|
|
|
while(Length)
|
|
{
|
|
/* Read DRW */
|
|
ERR = SWD_TransferFunction(REQ_AP|REQ_R|REQ_ADDR_3, Buffer, 3);
|
|
|
|
if (ERR == 0)
|
|
{
|
|
if (first)
|
|
{
|
|
Length--;
|
|
Buffer++;
|
|
}
|
|
first++;
|
|
}
|
|
else if (ERR == -2)
|
|
Length = 0;
|
|
SWD_DELAY();
|
|
SWD_DELAY();
|
|
}
|
|
}
|
|
|
|
RAM_CODE void SWD_W_SystemReg(void)
|
|
{
|
|
SWD_IO_init();
|
|
|
|
SWD_Connect();
|
|
|
|
SWD_Enable_Debug();
|
|
|
|
/* BIT24: enable cache clock */
|
|
SWD_W_REG(0x50000008, 0x09000803);
|
|
/* enable exchange memory clock */
|
|
SWD_W_REG(0x50000010, 0x1000);
|
|
}
|