Files
Gen4_R-Car_Trace32/2_Trunk/demo/arm/etc/usraccess/cp15.c
2025-10-14 09:52:32 +09:00

124 lines
3.7 KiB
C

/***********************************************************************
Code to access the registers of coprocessor 15 via a target program
using the TRACE32 User Controlled Memory Access (USR: memory class)
This example accesses the registers of coprocessor 15
by the following addressing scheme:
addr.bit 16-14: <op1>
addr.bit 12-10: <op2>
addr.bit 9-6: CRm
addr.bit 5-2: CRn
addr.bit 1-0: Byte within 32-bit coprocessor registers
Which results in the following assembler commands:
MCR/MRC p15, <op1>, Rd, CRn, CRm, <op2>
See readme.txt or look for command Data.USRACCESS in the manual.
Compile this file as ARM code.
$Date: 2014-01-09 19:57:21 +0100 (Thu, 09 Jan 2014) $
$Rev: 5954 $
***********************************************************************/
#include <stdint.h>
typedef struct {
uint32_t flashaddr; /* reserved (for compatibility to other access types using a target binary) */
uint32_t flashwidth; /* reserved (for compatibility to other access types using a target binary) */
uint32_t width; /* target memory access width */
uint32_t offset; /* reserved (for compatibility to other access types using a target binary) */
uint32_t addr; /* target memory adress */
uint32_t size; /* buffer size */
uint32_t reserved;
uint32_t status; /* IN: 5=read, 6=write, OUT: 0=ok, 0x100=fail */
uint8_t data[4096]; /* Transfer Buffer, size can be made smaller (DATA.USRACCESS command) */
/* 256 bytes of stack */
} UsrAccessParameter;
enum {
T32_USRACCESS_IDLE = 0x000,
T32_USRACCESS_READ = 0x005,
T32_USRACCESS_WRITE = 0x006,
T32_USRACCESS_ERROR = 0x100
};
extern uint32_t mrc(uint32_t data, uint32_t cmd);
extern uint32_t RdCtrlReg(void);
extern void WrCtrlReg(uint32_t data);
uint32_t ReadCP15(uint32_t addr)
{
/* MRC : Move to ARM Register from Coprocessor */
uint32_t cp_num = 15;
uint32_t CRn = (addr >> 0) & 0x0f;
uint32_t CRm = (addr >> 4) & 0x0f;
uint32_t op2 = (addr >> 8) & 0x03;
uint32_t op1 = (addr >> 12) & 0x07;
uint32_t Rd = 0;
uint32_t cmd = 0xEE100010 | op1<<21 | CRn<<16 | Rd<<12 | cp_num<<8 | op2<<5 | CRm;
if (addr == 1)
return RdCtrlReg();
return mrc(0,cmd);
}
void WriteCP15(uint32_t addr, uint32_t data)
{
/* MCR : Move to Coprocessor from ARM Register */
uint32_t cp_num = 15;
uint32_t CRn = (addr >> 0) & 0x0f;
uint32_t CRm = (addr >> 4) & 0x0f;
uint32_t op2 = (addr >> 8) & 0x03;
uint32_t op1 = (addr >> 12) & 0x07;
uint32_t Rd = 0;
uint32_t cmd = 0xEE000010 | op1<<21 | CRn<<16 | Rd<<12 | cp_num<<8 | op2<<5 | CRm;
if (addr == 1)
WrCtrlReg(data);
else
mrc(data,cmd);
}
__attribute__ ((section (".first")))
UsrAccessParameter * usraccess(UsrAccessParameter * param)
{
int i, nibble;
int size = param->size;
uint32_t addr = param->addr;
uint32_t data32 = 0;
if (param->status == T32_USRACCESS_READ) { /* data read ? */
for ( i=0; i<size; i++ ){
nibble = (addr + i) % 4;
if ( i==0 || nibble==0 ) {
data32 = ReadCP15(addr/4);
addr += 4;
}
param->data[i] = (data32 >> (8*nibble)) & 0xff; /* copy data bytes to buffer in little endian order */
}
} else if (param->status == T32_USRACCESS_WRITE) { /* data write ? */
const uint32_t mask[4] = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
for ( i=0; i<size; i++ ) {
nibble = (addr + i) % 4;
if ( (i == 0 && nibble != 0) || (size-i < 4 && nibble == 0) ) {
data32 = ReadCP15(addr/4);
}
data32 = (data32 & ~mask[nibble]) | ((param->data[i]<<(8*nibble)) & mask[nibble]); /* copy data32 from buffer in little endian order */
if ( nibble+1 == 4 || i+1 == size ) {
WriteCP15(addr/4, data32);
addr += 4;
}
}
}
param->status = T32_USRACCESS_IDLE;
return param;
}