From b00c3317ac1d27a513a95772120bd1cb05b56cf6 Mon Sep 17 00:00:00 2001 From: Ciro Cattuto Date: Thu, 16 Dec 2021 21:57:59 +0100 Subject: [PATCH] Implemented readBytes() and writeBytes()() Added methods to read/write non-word-aligned byte memory blocks. --- README.md | 2 ++ examples/rtt/rtt.js | 23 ++------------ src/dap/adi.ts | 77 +++++++++++++++++++++++++++++++++++++++++++++ src/dap/index.ts | 16 ++++++++++ 4 files changed, 98 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 5503736..14b9fc0 100644 --- a/README.md +++ b/README.md @@ -284,6 +284,8 @@ The `DAP` (Debug Access Port) layer exposes low-level access to ports, registers - [x] writeMem32() - [x] readBlock() - [x] writeBlock() +- [x] readBytes() +- [x] writeBytes() ### Processor diff --git a/examples/rtt/rtt.js b/examples/rtt/rtt.js index 2b80317..a22936c 100644 --- a/examples/rtt/rtt.js +++ b/examples/rtt/rtt.js @@ -109,33 +109,16 @@ class RTT { }).join('') } - async readBytes (addr, size) { - var sizeToRead = size; - let startOffset = addr % 4; - let endOffset = (addr + size) % 4; - - if (startOffset) { - addr -= startOffset; - sizeToRead += startOffset; - } - - if (endOffset) - sizeToRead += (4 - endOffset); - - var data32 = await this.processor.readBlock(addr, sizeToRead / 4); - return new Uint8Array(data32.buffer).slice(startOffset, startOffset + size); - } - async read (bufId) { var buf = this.bufUp[bufId]; buf.WrOff = await this.processor.readMem32(buf.bufAddr + 12); if (buf.WrOff > buf.RdOff) { - var data = await this.readBytes(buf.pBuffer + buf.RdOff, buf.WrOff - buf.RdOff); + var data = await processor.readBytes(buf.pBuffer + buf.RdOff, buf.WrOff - buf.RdOff); } else if (buf.WrOff < buf.RdOff) { - let data1 = await this.readBytes(buf.pBuffer + buf.RdOff, buf.SizeOfBuffer - buf.RdOff); - let data2 = await this.readBytes(buf.pBuffer, buf.WrOff); + let data1 = await processor.readBytes(buf.pBuffer + buf.RdOff, buf.SizeOfBuffer - buf.RdOff); + let data2 = await processor.readBytes(buf.pBuffer, buf.WrOff); var data = new Uint8Array(data1.length + data2.length); data.set(data1, 0); data.set(data2, data1.length); diff --git a/src/dap/adi.ts b/src/dap/adi.ts index f5a4eb5..b72610c 100644 --- a/src/dap/adi.ts +++ b/src/dap/adi.ts @@ -461,4 +461,81 @@ export class ADI implements DAP { index += chunkSize; } } + + /** + * Read a block of bytes from a memory access port register + * @param register ID of register to read from + * @param count The count of values to read + * @returns Promise of register data + */ + public async readBytes(register: number, count: number): Promise { + // read a word-aligned chunk of 32-bit words containing the requested range, then trim it + let bytesToRead = count; + const startOffset = register & 0x03; + const endOffset = (register + count) & 0x03; + + // include left-most 32-bit word + if (startOffset) { + register -= startOffset; + bytesToRead += startOffset; + } + + // include right-most 32-bit word + if (endOffset) { + bytesToRead += (4 - endOffset); + } + + const result = await this.readBlock(register, bytesToRead / 4); + return new Uint8Array(result.buffer).slice(startOffset, startOffset + count); + } + + /** + * Write a block of bytes to a memory access port register + * @param register ID of register to write to + * @param values The values to write + * @returns Promise + */ + public async writeBytes(register: number, values: Uint8Array): Promise { + let bytesToWrite = values.length; + let index = 0; + + // initial byte write + if ((bytesToWrite > 0) && (register & 0x01)) { + await this.writeMem8(register, values[index]); + bytesToWrite -= 1; + register += 1; + index += 1; + } + + // initial 16-bit word write + if ((bytesToWrite > 1) && (register & 0x02)) { + await this.writeMem16(register, values[index] | (values[index + 1] << 8)); + bytesToWrite -= 2; + register += 2; + index += 2; + } + + // chunk of word-aligned 32-bit words + if (bytesToWrite >= 4) { + const chunkSize = bytesToWrite - bytesToWrite % 4; + const chunk = new Uint32Array(values.slice(index, index + chunkSize).buffer); + await this.writeBlock(register, chunk); + bytesToWrite -= chunkSize; + register += chunkSize; + index += chunkSize; + } + + // trailing 16-bit word write + if (bytesToWrite > 1) { + await this.writeMem16(register, values[index] | (values[index + 1] << 8)); + bytesToWrite -= 2; + register += 2; + index += 2; + } + + // tailing byte write + if (bytesToWrite > 0) { + await this.writeMem8(register, values[index]); + } + } } diff --git a/src/dap/index.ts b/src/dap/index.ts index 06f7997..c5359d1 100644 --- a/src/dap/index.ts +++ b/src/dap/index.ts @@ -139,6 +139,22 @@ export interface DAP { * @returns Promise */ writeBlock(register: number, values: Uint32Array): Promise; + + /** + * Read a block of bytes from a memory access port register + * @param register ID of register to read from + * @param count The count of values to read + * @returns Promise of register data + */ + readBytes(register: number, count: number): Promise; + + /** + * Write a block of bytes to a memory access port register + * @param register ID of register to write to + * @param values The values to write + * @returns Promise + */ + writeBytes(register: number, values: Uint8Array): Promise; } export * from './adi';