3.4.1 About accessing registers

CADIRegRead() and CADIRegWrite() are used to access registers and process an array of accesses with elements of type CADIReg_t.

The elements of the array:

  • Specify the addressed register by its register number (ID).
  • Provide a buffer of 16 bytes for accesses.
  • Receive information about permitted access (read, write or read-write).
  • Optionally specify an offset for registers wider than 128 bits. As CADIReg_t data buffer can contain a maximum of only 16 bytes, which is 128 bits. Such registers must be accessed multiple times to return all of the register content. Each access uses an appropriate offset to specify a different bit range in the register.
  • Enable the target to indicate registers with undefined content.
Accessing registers in the target
// One way to implement a read access to a register with a width of 512 bits.
// "register_info" is a CADIRegInfo_t representing a register with a
// bitwidth of 512 bits, reading and displaying the register's contents;
// "cadi" is a pointer to a CADI object.
uint32_t regCount = (register_info.bitsWide + 127)/128;
uint32_t regWidthInBytes = (register_info.bitsWide + 7)/8;
eslapi::CADIReg_t* reg = new eslapi::CADIReg_t[regCount]();
for (uint32_t i = 0; i < regCount; i++)
{
   reg[i].regNumber = register_info.regNumber;
   reg[i].offset128 = i;
   reg[i].isUndefined = false;
   reg[i].attribute = register_info.attribute;
   memset(reg[i].bytes, 0, sizeof(uint8_t) * 16);
}
uint32_t numOfRegsWritten = 0;
eslapi::CADIReturn_t status = 
      cadi->CADIRegRead(regCount, reg, &numOfRegsWritten, 
                        0 /* no side effects */); 
// Check status.
if (numOfRegsWritten > 0)
{
   printf("0x");
}
// Start with the most significant bits to bring it in a readable form
for (uint32_t i = 0; i < numOfRegsWritten; i++)
{
   uint8_t currentBuffer = reg[numOfRegsWritten – 1 – i].bytes;
   uint32_t bytesInBuffer =
                     regWidthInBytes – ((numOfRegsWritten – 1 - i) * 16);
   if (bytesInBuffer >= 16)
      bytesInBuffer = 16;
   for (uint32_t j = bytesInBuffer; j > 0; j--)
   {
      printf("%02x", currentBuffer[j-1]);
   }
}
delete[] reg; 

In addition to the forwarded array of CADIReg_t data objects, the number of requested accesses is passed as regCount. The number of successful register accesses is returned in the numRegsRead (or numRegWritten) parameter.

Note:

The contents of the CADIReg_t data buffer must be accessed in little endian, even if the target uses a different endianness. That is, the element with the smallest index of the buffer array contains the least significant byte (LSB). This implicitly means that the access with offset 0, for registers wider than 128 bytes, addresses the 16 LSBs.

The caller sets the doSideEffects parameter to specify whether the target must perform side effects associated with the access:

  • If true, the target must do all side effects as usual.
  • If false, the target must decide which side effects are inevitable and must always be performed. Other side effects are not performed.

CADIRegRead() might have a side effect for a clear-on-read. Typically, a target must omit all side effects for a read access if the doSideEffects parameter is set to false. This corresponds to a debug read that must not interfere with the execution of the target.

A possible side effect for a write access to a register by CADIRegWrite() would be triggering an interrupt. For a write access, the target can decide which side effects to perform. It might be for example necessary to change the mode of a processor according to the contents of a register even if doSideEffects is set to false.

Non-ConfidentialPDF file icon PDF versionARM 100963_0200_00_en
Copyright © 2014–2017 ARM Limited or its affiliates. All rights reserved.