adiv5: Encode APnDP into register definition.
Clean up magic numbers in adiv5 calls. Removed old adiv5_dp_write_ap and adiv5_dp_read_ap.
This commit is contained in:
parent
6f5b1873d7
commit
2e785e56fa
90
src/adiv5.c
90
src/adiv5.c
@ -160,23 +160,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
|
|||||||
adiv5_dp_unref(dp);
|
adiv5_dp_unref(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adiv5_dp_write_ap(ADIv5_DP_t *dp, uint8_t addr, uint32_t value)
|
|
||||||
{
|
|
||||||
adiv5_dp_low_access(dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t adiv5_dp_read_ap(ADIv5_DP_t *dp, uint8_t addr)
|
|
||||||
{
|
|
||||||
uint32_t ret;
|
|
||||||
|
|
||||||
adiv5_dp_low_access(dp, ADIV5_LOW_AP, ADIV5_LOW_READ, addr, 0);
|
|
||||||
ret = adiv5_dp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
|
|
||||||
ADIV5_DP_RDBUFF, 0);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ap_check_error(struct target_s *target)
|
ap_check_error(struct target_s *target)
|
||||||
{
|
{
|
||||||
@ -194,26 +177,24 @@ ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len
|
|||||||
|
|
||||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||||
ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
||||||
ADIV5_AP_TAR, src);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ,
|
|
||||||
ADIV5_AP_DRW, 0);
|
|
||||||
while(--len) {
|
while(--len) {
|
||||||
*dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
*dest++ = adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
src += 4;
|
src += 4;
|
||||||
/* Check for 10 bit address overflow */
|
/* Check for 10 bit address overflow */
|
||||||
if ((src ^ osrc) & 0xfffffc00) {
|
if ((src ^ osrc) & 0xfffffc00) {
|
||||||
osrc = src;
|
osrc = src;
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
*dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
|
*dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ,
|
||||||
ADIV5_DP_RDBUFF, 0);
|
ADIV5_DP_RDBUFF, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -229,12 +210,10 @@ ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int
|
|||||||
|
|
||||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||||
ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
||||||
ADIV5_AP_TAR, src);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ,
|
|
||||||
ADIV5_AP_DRW, 0);
|
|
||||||
while(--len) {
|
while(--len) {
|
||||||
tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ,
|
tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ,
|
||||||
ADIV5_AP_DRW, 0);
|
ADIV5_AP_DRW, 0);
|
||||||
*dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF);
|
*dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF);
|
||||||
|
|
||||||
@ -242,13 +221,13 @@ ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int
|
|||||||
/* Check for 10 bit address overflow */
|
/* Check for 10 bit address overflow */
|
||||||
if ((src ^ osrc) & 0xfffffc00) {
|
if ((src ^ osrc) & 0xfffffc00) {
|
||||||
osrc = src;
|
osrc = src;
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmp = adiv5_dp_low_access(ap->dp, 0, 1, ADIV5_DP_RDBUFF, 0);
|
tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0);
|
||||||
*dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF);
|
*dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -263,25 +242,23 @@ ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len)
|
|||||||
|
|
||||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||||
ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
||||||
ADIV5_AP_TAR, src);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ,
|
|
||||||
ADIV5_AP_DRW, 0);
|
|
||||||
while(--len) {
|
while(--len) {
|
||||||
tmp = adiv5_dp_low_access(ap->dp, 1, 1, ADIV5_AP_DRW, 0);
|
tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
*dest++ = (tmp >> ((src & 0x3) << 3) & 0xFF);
|
*dest++ = (tmp >> ((src & 0x3) << 3) & 0xFF);
|
||||||
|
|
||||||
src++;
|
src++;
|
||||||
/* Check for 10 bit address overflow */
|
/* Check for 10 bit address overflow */
|
||||||
if ((src ^ osrc) & 0xfffffc00) {
|
if ((src ^ osrc) & 0xfffffc00) {
|
||||||
osrc = src;
|
osrc = src;
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
ADIV5_LOW_WRITE, ADIV5_AP_TAR, src);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
ADIV5_LOW_READ, ADIV5_AP_DRW, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmp = adiv5_dp_low_access(ap->dp, 0, 1, ADIV5_DP_RDBUFF, 0);
|
tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0);
|
||||||
*dest++ = (tmp >> ((src++ & 0x3) << 3) & 0xFF);
|
*dest++ = (tmp >> ((src++ & 0x3) << 3) & 0xFF);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -298,16 +275,15 @@ ap_mem_write_words(struct target_s *target, uint32_t dest, const uint32_t *src,
|
|||||||
|
|
||||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||||
ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
||||||
ADIV5_AP_TAR, dest);
|
|
||||||
while(len--) {
|
while(len--) {
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
ADIV5_AP_DRW, *src++);
|
ADIV5_AP_DRW, *src++);
|
||||||
dest += 4;
|
dest += 4;
|
||||||
/* Check for 10 bit address overflow */
|
/* Check for 10 bit address overflow */
|
||||||
if ((dest ^ odest) & 0xfffffc00) {
|
if ((dest ^ odest) & 0xfffffc00) {
|
||||||
odest = dest;
|
odest = dest;
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,17 +301,16 @@ ap_mem_write_halfwords(struct target_s *target, uint32_t dest, const uint16_t *s
|
|||||||
|
|
||||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||||
ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
||||||
ADIV5_AP_TAR, dest);
|
|
||||||
while(len--) {
|
while(len--) {
|
||||||
uint32_t tmp = (uint32_t)*src++ << ((dest & 2) << 3);
|
uint32_t tmp = (uint32_t)*src++ << ((dest & 2) << 3);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
ADIV5_AP_DRW, tmp);
|
ADIV5_AP_DRW, tmp);
|
||||||
dest += 2;
|
dest += 2;
|
||||||
/* Check for 10 bit address overflow */
|
/* Check for 10 bit address overflow */
|
||||||
if ((dest ^ odest) & 0xfffffc00) {
|
if ((dest ^ odest) & 0xfffffc00) {
|
||||||
odest = dest;
|
odest = dest;
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,17 +325,16 @@ ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, i
|
|||||||
|
|
||||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||||
ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
||||||
ADIV5_AP_TAR, dest);
|
|
||||||
while(len--) {
|
while(len--) {
|
||||||
uint32_t tmp = (uint32_t)*src++ << ((dest++ & 3) << 3);
|
uint32_t tmp = (uint32_t)*src++ << ((dest++ & 3) << 3);
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE,
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
ADIV5_AP_DRW, tmp);
|
ADIV5_AP_DRW, tmp);
|
||||||
|
|
||||||
/* Check for 10 bit address overflow */
|
/* Check for 10 bit address overflow */
|
||||||
if ((dest ^ odest) & 0xfffffc00) {
|
if ((dest ^ odest) & 0xfffffc00) {
|
||||||
odest = dest;
|
odest = dest;
|
||||||
adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP,
|
adiv5_dp_low_access(ap->dp,
|
||||||
ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,19 +403,19 @@ void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value)
|
|||||||
adiv5_ap_write(ap, ADIV5_AP_DRW, v);
|
adiv5_ap_write(ap, ADIV5_AP_DRW, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void adiv5_ap_write(ADIv5_AP_t *ap, uint8_t addr, uint32_t value)
|
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
|
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
|
||||||
((uint32_t)ap->apsel << 24)|(addr & 0xF0));
|
((uint32_t)ap->apsel << 24)|(addr & 0xF0));
|
||||||
adiv5_dp_write_ap(ap->dp, addr, value);
|
adiv5_dp_write(ap->dp, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint8_t addr)
|
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
|
||||||
{
|
{
|
||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
|
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
|
||||||
((uint32_t)ap->apsel << 24)|(addr & 0xF0));
|
((uint32_t)ap->apsel << 24)|(addr & 0xF0));
|
||||||
ret = adiv5_dp_read_ap(ap->dp, addr);
|
ret = adiv5_dp_read(ap->dp, addr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +36,13 @@
|
|||||||
#define IR_DPACC 0xA
|
#define IR_DPACC 0xA
|
||||||
#define IR_APACC 0xB
|
#define IR_APACC 0xB
|
||||||
|
|
||||||
static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value);
|
static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value);
|
||||||
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr);
|
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr);
|
||||||
|
|
||||||
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
|
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
|
||||||
|
|
||||||
static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
|
static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
||||||
uint8_t addr, uint32_t value);
|
uint16_t addr, uint32_t value);
|
||||||
|
|
||||||
|
|
||||||
void adiv5_jtag_dp_handler(jtag_dev_t *dev)
|
void adiv5_jtag_dp_handler(jtag_dev_t *dev)
|
||||||
@ -60,35 +60,36 @@ void adiv5_jtag_dp_handler(jtag_dev_t *dev)
|
|||||||
adiv5_dp_init(dp);
|
adiv5_dp_init(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value)
|
static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, addr, value);
|
adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr)
|
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr)
|
||||||
{
|
{
|
||||||
adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, addr, 0);
|
adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
|
||||||
return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
|
return adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ,
|
||||||
ADIV5_DP_RDBUFF, 0);
|
ADIV5_DP_RDBUFF, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp)
|
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp)
|
||||||
{
|
{
|
||||||
adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ,
|
adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_CTRLSTAT, 0);
|
||||||
ADIV5_DP_CTRLSTAT, 0);
|
return adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE,
|
||||||
return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE,
|
|
||||||
ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32;
|
ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
|
static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
||||||
uint8_t addr, uint32_t value)
|
uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
|
bool APnDP = addr & ADIV5_APnDP;
|
||||||
|
addr &= 0xff;
|
||||||
uint64_t request, response;
|
uint64_t request, response;
|
||||||
uint8_t ack;
|
uint8_t ack;
|
||||||
|
|
||||||
request = ((uint64_t)value << 3) | ((addr >> 1) & 0x06) | (RnW?1:0);
|
request = ((uint64_t)value << 3) | ((addr >> 1) & 0x06) | (RnW?1:0);
|
||||||
|
|
||||||
jtag_dev_write_ir(dp->dev, APnDP?IR_APACC:IR_DPACC);
|
jtag_dev_write_ir(dp->dev, APnDP ? IR_APACC : IR_DPACC);
|
||||||
|
|
||||||
int tries = 1000;
|
int tries = 1000;
|
||||||
do {
|
do {
|
||||||
|
@ -33,13 +33,13 @@
|
|||||||
#define SWDP_ACK_WAIT 0x02
|
#define SWDP_ACK_WAIT 0x02
|
||||||
#define SWDP_ACK_FAULT 0x04
|
#define SWDP_ACK_FAULT 0x04
|
||||||
|
|
||||||
static void adiv5_swdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value);
|
static void adiv5_swdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value);
|
||||||
static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint8_t addr);
|
static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr);
|
||||||
|
|
||||||
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp);
|
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp);
|
||||||
|
|
||||||
static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
|
static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
||||||
uint8_t addr, uint32_t value);
|
uint16_t addr, uint32_t value);
|
||||||
|
|
||||||
|
|
||||||
int adiv5_swdp_scan(void)
|
int adiv5_swdp_scan(void)
|
||||||
@ -78,14 +78,20 @@ int adiv5_swdp_scan(void)
|
|||||||
return target_list?1:0;
|
return target_list?1:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void adiv5_swdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value)
|
static void adiv5_swdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
adiv5_swdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, addr, value);
|
adiv5_swdp_low_access(dp, ADIV5_LOW_WRITE, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint8_t addr)
|
static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr)
|
||||||
{
|
{
|
||||||
return adiv5_swdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, addr, 0);
|
if (addr & ADIV5_APnDP) {
|
||||||
|
adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
|
||||||
|
return adiv5_dp_low_access(dp, ADIV5_LOW_READ,
|
||||||
|
ADIV5_DP_RDBUFF, 0);
|
||||||
|
} else {
|
||||||
|
return adiv5_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp)
|
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp)
|
||||||
@ -111,9 +117,11 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW,
|
static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
||||||
uint8_t addr, uint32_t value)
|
uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
|
bool APnDP = addr & ADIV5_APnDP;
|
||||||
|
addr &= 0xff;
|
||||||
uint8_t request = 0x81;
|
uint8_t request = 0x81;
|
||||||
uint32_t response;
|
uint32_t response;
|
||||||
uint8_t ack;
|
uint8_t ack;
|
||||||
|
@ -359,20 +359,23 @@ cortexm_regs_read(struct target_s *target, void *data)
|
|||||||
|
|
||||||
/* Map the banked data registers (0x10-0x1c) to the
|
/* Map the banked data registers (0x10-0x1c) to the
|
||||||
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
|
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_TAR, CORTEXM_DHCSR);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR);
|
||||||
|
|
||||||
/* Walk the regnum_cortex_m array, reading the registers it
|
/* Walk the regnum_cortex_m array, reading the registers it
|
||||||
* calls out. */
|
* calls out. */
|
||||||
adiv5_ap_write(ap, ADIV5_AP_DB(1), regnum_cortex_m[0]); /* Required to switch banks */
|
adiv5_ap_write(ap, ADIV5_AP_DB(1), regnum_cortex_m[0]); /* Required to switch banks */
|
||||||
*regs++ = adiv5_dp_read_ap(ap->dp, ADIV5_AP_DB(2));
|
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2));
|
||||||
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
|
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), regnum_cortex_m[i]);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1),
|
||||||
*regs++ = adiv5_dp_read_ap(ap->dp, ADIV5_AP_DB(2));
|
regnum_cortex_m[i]);
|
||||||
|
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2));
|
||||||
}
|
}
|
||||||
if (target->target_options & TOPT_FLAVOUR_V7MF)
|
if (target->target_options & TOPT_FLAVOUR_V7MF)
|
||||||
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
|
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), regnum_cortex_mf[i]);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
*regs++ = adiv5_dp_read_ap(ap->dp, ADIV5_AP_DB(2));
|
ADIV5_AP_DB(1),
|
||||||
|
regnum_cortex_mf[i]);
|
||||||
|
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -391,22 +394,26 @@ cortexm_regs_write(struct target_s *target, const void *data)
|
|||||||
|
|
||||||
/* Map the banked data registers (0x10-0x1c) to the
|
/* Map the banked data registers (0x10-0x1c) to the
|
||||||
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
|
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_TAR, CORTEXM_DHCSR);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR);
|
||||||
|
|
||||||
/* Walk the regnum_cortex_m array, writing the registers it
|
/* Walk the regnum_cortex_m array, writing the registers it
|
||||||
* calls out. */
|
* calls out. */
|
||||||
adiv5_ap_write(ap, ADIV5_AP_DB(2), *regs++); /* Required to switch banks */
|
adiv5_ap_write(ap, ADIV5_AP_DB(2), *regs++); /* Required to switch banks */
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), 0x10000 | regnum_cortex_m[0]);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1),
|
||||||
|
0x10000 | regnum_cortex_m[0]);
|
||||||
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
|
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(2), *regs++);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1),
|
ADIV5_AP_DB(2), *regs++);
|
||||||
0x10000 | regnum_cortex_m[i]);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1),
|
||||||
|
0x10000 | regnum_cortex_m[i]);
|
||||||
}
|
}
|
||||||
if (target->target_options & TOPT_FLAVOUR_V7MF)
|
if (target->target_options & TOPT_FLAVOUR_V7MF)
|
||||||
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
|
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(2), *regs++);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1),
|
ADIV5_AP_DB(2), *regs++);
|
||||||
0x10000 | regnum_cortex_mf[i]);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
|
||||||
|
ADIV5_AP_DB(1),
|
||||||
|
0x10000 | regnum_cortex_mf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -24,12 +24,16 @@
|
|||||||
#include "jtag_scan.h"
|
#include "jtag_scan.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
|
||||||
|
#define ADIV5_APnDP 0x100
|
||||||
|
#define ADIV5_DP_REG(x) (x)
|
||||||
|
#define ADIV5_AP_REG(x) (ADIV5_APnDP | (x))
|
||||||
|
|
||||||
/* ADIv5 DP Register addresses */
|
/* ADIv5 DP Register addresses */
|
||||||
#define ADIV5_DP_IDCODE 0x0
|
#define ADIV5_DP_IDCODE ADIV5_DP_REG(0x0)
|
||||||
#define ADIV5_DP_ABORT 0x0
|
#define ADIV5_DP_ABORT ADIV5_DP_REG(0x0)
|
||||||
#define ADIV5_DP_CTRLSTAT 0x4
|
#define ADIV5_DP_CTRLSTAT ADIV5_DP_REG(0x4)
|
||||||
#define ADIV5_DP_SELECT 0x8
|
#define ADIV5_DP_SELECT ADIV5_DP_REG(0x8)
|
||||||
#define ADIV5_DP_RDBUFF 0xC
|
#define ADIV5_DP_RDBUFF ADIV5_DP_REG(0xC)
|
||||||
|
|
||||||
/* AP Abort Register (ABORT) */
|
/* AP Abort Register (ABORT) */
|
||||||
/* Bits 31:5 - Reserved */
|
/* Bits 31:5 - Reserved */
|
||||||
@ -63,15 +67,15 @@
|
|||||||
|
|
||||||
|
|
||||||
/* ADIv5 MEM-AP Registers */
|
/* ADIv5 MEM-AP Registers */
|
||||||
#define ADIV5_AP_CSW 0x00
|
#define ADIV5_AP_CSW ADIV5_AP_REG(0x00)
|
||||||
#define ADIV5_AP_TAR 0x04
|
#define ADIV5_AP_TAR ADIV5_AP_REG(0x04)
|
||||||
/* 0x08 - Reserved */
|
/* 0x08 - Reserved */
|
||||||
#define ADIV5_AP_DRW 0x0C
|
#define ADIV5_AP_DRW ADIV5_AP_REG(0x0C)
|
||||||
#define ADIV5_AP_DB(x) (0x10 + (4*(x)))
|
#define ADIV5_AP_DB(x) ADIV5_AP_REG(0x10 + (4*(x)))
|
||||||
/* 0x20:0xF0 - Reserved */
|
/* 0x20:0xF0 - Reserved */
|
||||||
#define ADIV5_AP_CFG 0xF4
|
#define ADIV5_AP_CFG ADIV5_AP_REG(0xF4)
|
||||||
#define ADIV5_AP_BASE 0xF8
|
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
||||||
#define ADIV5_AP_IDR 0xFC
|
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
|
||||||
|
|
||||||
/* AP Control and Status Word (CSW) */
|
/* AP Control and Status Word (CSW) */
|
||||||
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)
|
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)
|
||||||
@ -93,11 +97,9 @@
|
|||||||
#define ADIV5_AP_CSW_SIZE_WORD (2u << 0)
|
#define ADIV5_AP_CSW_SIZE_WORD (2u << 0)
|
||||||
#define ADIV5_AP_CSW_SIZE_MASK (7u << 0)
|
#define ADIV5_AP_CSW_SIZE_MASK (7u << 0)
|
||||||
|
|
||||||
/* Constants to make RnW and APnDP parameters more clear in code */
|
/* Constants to make RnW parameters more clear in code */
|
||||||
#define ADIV5_LOW_WRITE 0
|
#define ADIV5_LOW_WRITE 0
|
||||||
#define ADIV5_LOW_READ 1
|
#define ADIV5_LOW_READ 1
|
||||||
#define ADIV5_LOW_DP 0
|
|
||||||
#define ADIV5_LOW_AP 1
|
|
||||||
|
|
||||||
/* Try to keep this somewhat absract for later adding SW-DP */
|
/* Try to keep this somewhat absract for later adding SW-DP */
|
||||||
typedef struct ADIv5_DP_s {
|
typedef struct ADIv5_DP_s {
|
||||||
@ -107,13 +109,13 @@ typedef struct ADIv5_DP_s {
|
|||||||
|
|
||||||
bool allow_timeout;
|
bool allow_timeout;
|
||||||
|
|
||||||
void (*dp_write)(struct ADIv5_DP_s *dp, uint8_t addr, uint32_t value);
|
void (*dp_write)(struct ADIv5_DP_s *dp, uint16_t addr, uint32_t value);
|
||||||
uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint8_t addr);
|
uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr);
|
||||||
|
|
||||||
uint32_t (*error)(struct ADIv5_DP_s *dp);
|
uint32_t (*error)(struct ADIv5_DP_s *dp);
|
||||||
|
|
||||||
uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW,
|
uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t RnW,
|
||||||
uint8_t addr, uint32_t value);
|
uint16_t addr, uint32_t value);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
jtag_dev_t *dev;
|
jtag_dev_t *dev;
|
||||||
@ -121,12 +123,12 @@ typedef struct ADIv5_DP_s {
|
|||||||
};
|
};
|
||||||
} ADIv5_DP_t;
|
} ADIv5_DP_t;
|
||||||
|
|
||||||
static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value)
|
static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
dp->dp_write(dp, addr, value);
|
dp->dp_write(dp, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint8_t addr)
|
static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
|
||||||
{
|
{
|
||||||
return dp->dp_read(dp, addr);
|
return dp->dp_read(dp, addr);
|
||||||
}
|
}
|
||||||
@ -136,10 +138,10 @@ static inline uint32_t adiv5_dp_error(ADIv5_DP_t *dp)
|
|||||||
return dp->error(dp);
|
return dp->error(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP,
|
static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
|
||||||
uint8_t RnW, uint8_t addr, uint32_t value)
|
uint16_t addr, uint32_t value)
|
||||||
{
|
{
|
||||||
return dp->low_access(dp, APnDP, RnW, addr, value);
|
return dp->low_access(dp, RnW, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct ADIv5_AP_s {
|
typedef struct ADIv5_AP_s {
|
||||||
@ -164,9 +166,6 @@ void adiv5_ap_ref(ADIv5_AP_t *ap);
|
|||||||
void adiv5_dp_unref(ADIv5_DP_t *dp);
|
void adiv5_dp_unref(ADIv5_DP_t *dp);
|
||||||
void adiv5_ap_unref(ADIv5_AP_t *ap);
|
void adiv5_ap_unref(ADIv5_AP_t *ap);
|
||||||
|
|
||||||
void adiv5_dp_write_ap(ADIv5_DP_t *dp, uint8_t addr, uint32_t value);
|
|
||||||
uint32_t adiv5_dp_read_ap(ADIv5_DP_t *dp, uint8_t addr);
|
|
||||||
|
|
||||||
uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr);
|
uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr);
|
||||||
void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value);
|
void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value);
|
||||||
uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr);
|
uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr);
|
||||||
@ -174,8 +173,8 @@ void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value);
|
|||||||
uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr);
|
uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr);
|
||||||
void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value);
|
void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value);
|
||||||
|
|
||||||
void adiv5_ap_write(ADIv5_AP_t *ap, uint8_t addr, uint32_t value);
|
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
|
||||||
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint8_t addr);
|
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr);
|
||||||
|
|
||||||
void adiv5_jtag_dp_handler(jtag_dev_t *dev);
|
void adiv5_jtag_dp_handler(jtag_dev_t *dev);
|
||||||
int adiv5_swdp_scan(void);
|
int adiv5_swdp_scan(void);
|
||||||
|
11
src/lmi.c
11
src/lmi.c
@ -131,17 +131,18 @@ int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
|||||||
adiv5_ap_write(ap, 0x00, 0xA2000052);
|
adiv5_ap_write(ap, 0x00, 0xA2000052);
|
||||||
|
|
||||||
/* select Flash Control */
|
/* select Flash Control */
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, 0x04, 0x400FD000);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, 0x04, 0x400FD000);
|
||||||
|
|
||||||
while(len) {
|
while(len) {
|
||||||
/* write address to FMA */
|
/* write address to FMA */
|
||||||
adiv5_ap_write(ap, 0x10, addr); /* Required to switch banks */
|
adiv5_ap_write(ap, ADIV5_AP_DB(0), addr); /* Required to switch banks */
|
||||||
/* set ERASE bit in FMC */
|
/* set ERASE bit in FMC */
|
||||||
adiv5_dp_low_access(ap->dp, 1, 0, 0x08, 0xA4420002);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(2), 0xA4420002);
|
||||||
/* Read FMC to poll for ERASE bit */
|
/* Read FMC to poll for ERASE bit */
|
||||||
adiv5_dp_low_access(ap->dp, 1, 1, 0x08, 0);
|
adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DB(2), 0);
|
||||||
do {
|
do {
|
||||||
tmp = adiv5_dp_low_access(ap->dp, 1, 1, 0x08, 0);
|
tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ,
|
||||||
|
ADIV5_AP_DB(2), 0);
|
||||||
} while (tmp & 2);
|
} while (tmp & 2);
|
||||||
|
|
||||||
len -= 0x400;
|
len -= 0x400;
|
||||||
|
@ -553,7 +553,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
|
|||||||
|
|
||||||
/* Partial, manual page write */
|
/* Partial, manual page write */
|
||||||
for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) {
|
for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) {
|
||||||
adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]);
|
adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock */
|
/* Unlock */
|
||||||
@ -578,7 +578,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
|
|||||||
|
|
||||||
/* Full, automatic page write */
|
/* Full, automatic page write */
|
||||||
for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) {
|
for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) {
|
||||||
adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]);
|
adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user