Skip to content

Commit 9e6f1a6

Browse files
authored
Merge pull request #16 from andrewparlane/master
MEMAP: Fixing bug with auto TAR increment (Issue #15).
2 parents 7371533 + bf7ab2b commit 9e6f1a6

File tree

1 file changed

+128
-92
lines changed

1 file changed

+128
-92
lines changed

src/libswd_memap.c

Lines changed: 128 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ int libswd_memap_read_char(libswd_ctx_t *libswdctx, libswd_operation_t operation
209209
return LIBSWD_ERROR_BADOPCODE;
210210

211211
int i, loc, res=0, accsize=0, *memapdrw;
212-
int chunk, chunks, chunksize=1024;
213212
float tdeltam;
214213
struct timeval tstart, tstop;
215214

@@ -285,41 +284,54 @@ int libswd_memap_read_char(libswd_ctx_t *libswdctx, libswd_operation_t operation
285284
else
286285
{
287286
// Use TAR Auto Increment (faster).
288-
// 2^10 chunks are used due to TAR Auto Increment limitations.
287+
// TAR auto increment is only guaranteed to work on the bottom 10 bits
288+
// of the TAR register. Above that it is implementation defined.
289+
// We use 1024 byte chunks as it will work on every platform
290+
// and one TAR write every 1024 bytes is not adding too much overhead.
291+
const unsigned int BOUNDARY = 1024;
292+
unsigned int i;
293+
289294
// Check if packed transfer, if so use word access.
290295
if (libswdctx->log.memap.csw&LIBSWD_MEMAP_CSW_ADDRINC_PACKED) accsize=4;
291-
chunks=count/chunksize;
292-
for (chunk=0;chunk*chunksize<count;chunk++)
296+
297+
for (loc = addr, i = 0; loc < (addr + count); loc += accsize, i+= accsize)
293298
{
294299
int tmp;
295300
int drw_shift;
296-
loc=addr+chunk*chunksize;
301+
297302
// Calculate the offset in DRW where the data should be
298303
// see Data byte-laning in the ARM debug interface v5 documentation
299304
// note: this only works for little endian systems.
300305
drw_shift=8*(loc%4);
301-
// Pass address to TAR register.
302-
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
303-
if (res<0) goto libswd_memap_read_char_error;
304-
libswdctx->log.memap.tar=loc;
305-
for (i=0;i<chunksize;i+=accsize)
306+
307+
// only write the TAR register, if this is the first time through the loop.
308+
// or if we've passed over the boundary where TAR auto inc isn't guaranteed
309+
// to work anymore.
310+
if (loc == addr ||
311+
(loc % BOUNDARY) == 0)
306312
{
307-
if ((chunk*chunksize)+i>=count) break;
308-
// Measure transfer speed.
309-
gettimeofday(&tstop, NULL);
310-
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
311-
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
312-
"LIBSWD_I: libswd_memap_read_char() reading address 0x%08X (chunk 0x%X/0x%X, speed %fKB/s)\r",
313-
loc+i, chunk, chunks, count/tdeltam);
314-
fflush(0);
315-
// Implode and Write data to DRW register.
316-
res=libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &memapdrw);
313+
// Pass address to TAR register.
314+
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
317315
if (res<0) goto libswd_memap_read_char_error;
318-
libswdctx->log.memap.drw=*memapdrw;
319-
// apply the data byte-laning shift
320-
tmp=*memapdrw >>= drw_shift;
321-
memcpy((void*)data+(chunk*chunksize)+i, &tmp, accsize);
316+
libswdctx->log.memap.tar=loc;
322317
}
318+
319+
// Measure transfer speed.
320+
gettimeofday(&tstop, NULL);
321+
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
322+
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
323+
"LIBSWD_I: libswd_memap_read_char() reading address 0x%08X (speed %fKB/s)\r",
324+
loc, count/tdeltam);
325+
fflush(0);
326+
327+
// Read data from the DRW register.
328+
res=libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &memapdrw);
329+
if (res<0) goto libswd_memap_read_char_error;
330+
libswdctx->log.memap.drw=*memapdrw;
331+
332+
// apply the data byte-laning shift
333+
tmp=*memapdrw >>= drw_shift;
334+
memcpy((void*)data + i, &tmp, accsize);
323335
}
324336
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO, "\n");
325337
}
@@ -440,7 +452,6 @@ int libswd_memap_read_int(libswd_ctx_t *libswdctx, libswd_operation_t operation,
440452
return LIBSWD_ERROR_BADOPCODE;
441453

442454
int i, loc, res, *memapdrw;
443-
int chunk, chunks, chunksize=1024;
444455
float tdeltam;
445456
struct timeval tstart, tstop;
446457

@@ -483,32 +494,40 @@ int libswd_memap_read_int(libswd_ctx_t *libswdctx, libswd_operation_t operation,
483494
else
484495
{
485496
// Use TAR Auto Increment (faster).
486-
// 2^10 chunks are used due to TAR Auto Increment limitations.
487-
// Check if packed transfer, if so use word access.
488-
chunks=count/chunksize;
489-
for (chunk=0;chunk*chunksize<count;chunk++)
497+
// TAR auto increment is only guaranteed to work on the bottom 10 bits
498+
// of the TAR register. Above that it is implementation defined.
499+
// We use 1024 byte chunks as it will work on every platform
500+
// and one TAR write every 1024 bytes is not adding too much overhead.
501+
const unsigned int BOUNDARY = 1024;
502+
unsigned int i;
503+
504+
for (loc = addr, i = 0; loc < (addr + (count * 4)); loc += 4, i++)
490505
{
491-
loc=addr+chunk*chunksize;
492-
// Pass address to TAR register.
493-
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
494-
if (res<0) goto libswd_memap_read_int_error;
495-
libswdctx->log.memap.tar=loc;
496-
for (i=0;i<chunksize;i++)
506+
// only write the TAR register, if this is the first time through the loop.
507+
// or if we've passed over the boundary where TAR auto inc isn't guaranteed
508+
// to work anymore.
509+
if (loc == addr ||
510+
(loc % BOUNDARY) == 0)
497511
{
498-
if ((chunk*chunksize)+(i*4)>=count) break;
499-
// Measure transfer speed.
500-
gettimeofday(&tstop, NULL);
501-
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
502-
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
503-
"LIBSWD_I: libswd_memap_read_int() reading address 0x%08X (chunk 0x%X/0x%X, speed %fKB/s)\r",
504-
loc+(i*4), chunk, chunks, count*4/tdeltam );
505-
fflush(0);
506-
// Write data to DRW register.
507-
res=libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &memapdrw);
512+
// Pass address to TAR register.
513+
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
508514
if (res<0) goto libswd_memap_read_int_error;
509-
libswdctx->log.memap.drw=*memapdrw;
510-
data[chunk*chunksize+i]=*memapdrw;
515+
libswdctx->log.memap.tar=loc;
511516
}
517+
518+
// Measure transfer speed.
519+
gettimeofday(&tstop, NULL);
520+
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
521+
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
522+
"LIBSWD_I: libswd_memap_read_int() reading address 0x%08X (speed %fKB/s)\r",
523+
loc, count*4/tdeltam );
524+
fflush(0);
525+
526+
// Read data from the DRW register.
527+
res=libswd_ap_read(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &memapdrw);
528+
if (res<0) goto libswd_memap_read_int_error;
529+
libswdctx->log.memap.drw=*memapdrw;
530+
data[i]=*memapdrw;
512531
}
513532
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO, "\n");
514533
}
@@ -622,7 +641,6 @@ int libswd_memap_write_char(libswd_ctx_t *libswdctx, libswd_operation_t operatio
622641
return LIBSWD_ERROR_BADOPCODE;
623642

624643
int i, loc, res=0, accsize=0;
625-
int chunk, chunks, chunksize=1024;
626644
float tdeltam;
627645
struct timeval tstart, tstop;
628646

@@ -696,39 +714,50 @@ int libswd_memap_write_char(libswd_ctx_t *libswdctx, libswd_operation_t operatio
696714
else
697715
{
698716
// Use TAR Auto Increment (faster).
699-
// 2^10 chunks are used due to TAR Auto Increment limitations.
717+
// TAR auto increment is only guaranteed to work on the bottom 10 bits
718+
// of the TAR register. Above that it is implementation defined.
719+
// We use 1024 byte chunks as it will work on every platform
720+
// and one TAR write every 1024 bytes is not adding too much overhead.
721+
const unsigned int BOUNDARY = 1024;
722+
unsigned int i;
723+
700724
// Check if packed transfer, if so use word access.
701725
if (libswdctx->log.memap.csw&LIBSWD_MEMAP_CSW_ADDRINC_PACKED) accsize=4;
702-
chunks=count/chunksize;
703-
for (chunk=0;chunk*chunksize<count;chunk++)
726+
727+
for (loc = addr, i = 0; loc < (addr + count); loc += accsize, i+= accsize)
704728
{
705729
int drw_shift;
706-
loc=addr+chunk*chunksize;
730+
707731
// Calculate the offset in DRW where the data should go
708732
// see Data byte-laning in the ARM debug interface v5 documentation
709733
// note: this only works for little endian systems.
710734
drw_shift=8*(loc%4);
711-
// Pass address to TAR register.
712-
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
713-
if (res<0) goto libswd_memap_write_char_error;
714-
libswdctx->log.memap.tar=loc;
715-
for (i=0;i<chunksize;i+=accsize)
735+
736+
// only write the TAR register, if this is the first time through the loop.
737+
// or if we've passed over the boundary where TAR auto inc isn't guaranteed
738+
// to work anymore.
739+
if (loc == addr ||
740+
(loc % BOUNDARY) == 0)
716741
{
717-
if ((chunk*chunksize)+i>=count) break;
718-
// Measure transfer speed.
719-
gettimeofday(&tstop, NULL);
720-
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
721-
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
722-
"LIBSWD_I: libswd_memap_write_char() writing address 0x%08X (chunk 0x%X/0x%X, speed %fKB/s)\r",
723-
loc+i, chunk, chunks, count/tdeltam );
724-
fflush(0);
725-
// Implode and Write data to DRW register.
726-
memcpy((void*)&libswdctx->log.memap.drw, data+(chunk*chunksize)+i, accsize);
727-
// apply the data byte-laning shift
728-
libswdctx->log.memap.drw <<= drw_shift;
729-
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &libswdctx->log.memap.drw);
742+
// Pass address to TAR register.
743+
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
730744
if (res<0) goto libswd_memap_write_char_error;
745+
libswdctx->log.memap.tar=loc;
731746
}
747+
748+
// Measure transfer speed.
749+
gettimeofday(&tstop, NULL);
750+
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
751+
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
752+
"LIBSWD_I: libswd_memap_write_char() writing address 0x%08X (speed %fKB/s)\r",
753+
loc, count/tdeltam );
754+
fflush(0);
755+
756+
// apply the data byte-laning shift and write to the DRW register
757+
memcpy((void*)&libswdctx->log.memap.drw, data + i, accsize);
758+
libswdctx->log.memap.drw <<= drw_shift;
759+
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &libswdctx->log.memap.drw);
760+
if (res<0) goto libswd_memap_write_char_error;
732761
}
733762
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO, "\n");
734763
}
@@ -845,7 +874,6 @@ int libswd_memap_write_int(libswd_ctx_t *libswdctx, libswd_operation_t operation
845874
return LIBSWD_ERROR_BADOPCODE;
846875

847876
int i, loc, res=0;
848-
int chunk, chunks, chunksize=1024;
849877
float tdeltam;
850878
struct timeval tstart, tstop;
851879

@@ -887,31 +915,39 @@ int libswd_memap_write_int(libswd_ctx_t *libswdctx, libswd_operation_t operation
887915
else
888916
{
889917
// Use TAR Auto Increment (faster).
890-
// 2^10 chunks are used due to TAR Auto Increment limitations.
891-
// Check if packed transfer, if so use word access.
892-
chunks=count/chunksize;
893-
for (chunk=0;chunk*chunksize<count;chunk++)
918+
// TAR auto increment is only guaranteed to work on the bottom 10 bits
919+
// of the TAR register. Above that it is implementation defined.
920+
// We use 1024 byte chunks as it will work on every platform
921+
// and one TAR write every 1024 bytes is not adding too much overhead.
922+
const unsigned int BOUNDARY = 1024;
923+
unsigned int i;
924+
925+
for (loc = addr, i = 0; loc < (addr + (count * 4)); loc += 4, i++)
894926
{
895-
loc=addr+chunk*chunksize;
896-
// Pass address to TAR register.
897-
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
898-
if (res<0) goto libswd_memap_write_int_error;
899-
libswdctx->log.memap.tar=loc;
900-
for (i=0;i<chunksize;i++)
927+
// only write the TAR register, if this is the first time through the loop.
928+
// or if we've passed over the boundary where TAR auto inc isn't guaranteed
929+
// to work anymore.
930+
if (loc == addr ||
931+
(loc % BOUNDARY) == 0)
901932
{
902-
if ((chunk*chunksize)+(i*4)>=count) break;
903-
// Measure transfer speed.
904-
gettimeofday(&tstop, NULL);
905-
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
906-
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
907-
"LIBSWD_I: libswd_memap_write_int() writing address 0x%08X (chunk 0x%X/0x%X speed %fKB/s)\r",
908-
loc+(i*4), chunk, chunks, count*4/tdeltam );
909-
fflush(0);
910-
// Implode and Write data to DRW register.
911-
libswdctx->log.memap.drw=data[chunk*chunksize+i];
912-
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &libswdctx->log.memap.drw);
933+
// Pass address to TAR register.
934+
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_TAR_ADDR, &loc);
913935
if (res<0) goto libswd_memap_write_int_error;
936+
libswdctx->log.memap.tar=loc;
914937
}
938+
939+
// Measure transfer speed.
940+
gettimeofday(&tstop, NULL);
941+
tdeltam=fabsf((tstop.tv_sec-tstart.tv_sec)*1000+(tstop.tv_usec-tstart.tv_usec)/1000);
942+
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO,
943+
"LIBSWD_I: libswd_memap_write_int() writing address 0x%08X (speed %fKB/s)\r",
944+
loc, count*4/tdeltam );
945+
fflush(0);
946+
947+
// Write data to DRW register.
948+
libswdctx->log.memap.drw=data[i];
949+
res=libswd_ap_write(libswdctx, LIBSWD_OPERATION_EXECUTE, LIBSWD_MEMAP_DRW_ADDR, &libswdctx->log.memap.drw);
950+
if (res<0) goto libswd_memap_write_int_error;
915951
}
916952
libswd_log(libswdctx, LIBSWD_LOGLEVEL_INFO, "\n");
917953
}

0 commit comments

Comments
 (0)