how to access to physical address on VXworks in C/c++? - arm

I am trying to read FPGA (altera cyclone IV) registers from ARM cortex A8 ona board with Vxworks 6.9.
for example
#define My_FPGA_IP_Address_Base 0x00000400
#define mm_avalon 0x25000000
int main(){
vxWorks_read_fromAddr (mm_avalon + My_FPGA_IP_Address_Base) ; //how can I get this on Vxworks
}
Could anyone help me out, thanks in advance

You should be able to access the register using a normal pointer with a virtual address.
int* myRegister = mm_avalon + My_FPGA_IP_Address_Base + registerOffset;
int myRegisterValue = *myRegister;
or
*myRegister = 10;
Assuming your register is write enable.
Look at this post which seems related for more info.

Related

Get maximum available register for Linux PCI device

I am currently debugging a Linux kernel driver.
I want to sweep a PCI device's mmio registers to scan for certain information.
This is the function I wrote so far.
void _sweep_registers(struct pci_dev *dev)
{
int i;
int activecontrolstatus;
int activestatus;
for (i = 0; i < AMD_P2C_MSG_INTSTS; i++) {
activecontrolstatus = readl(privdata->mmio + i);
activestatus = activecontrolstatus >> 4;
dev_info(&dev->dev, "activecontrolstatus = %d / activestatus = %d",
activecontrolstatus, activestatus);
}
}
Currently I am reading mmio until what's specified in AMD_P2C_MSG_INTSTS (which is 0x10694).
But how far can I actually go?
I have zero knowledge of Linux kernel development and only rudimentary knowledge of C.
Background
My goal is to find information about which sensors of the AMD Sensor Fusion Hub are marked as active.
They should be under the register 0x1068C, but are not on my system (it's 0x0, but at least an accelerometer is available, so the bitmask should at least match 0x1).
I want to see, whether they are stored somewhere else.

Can not able to read data from custom AXI peripheral register

I am working with a Zynq board where a custom AXI 4 lite slave peripheral is created and then added from the IP Repository.
And created a synthesizable custom IP in vivado (which is sine wave IP)and also wrote a C code for reading this IP output ( i want to read a data from the register). But somehow it shows something diff. instead of what I expect.
Here I'm attaching a screenshot and my c code for that.
But in teraterm it shows some garbage memory state.
Here, I'm expecting a sinewave output. ( In digit form )
Pls, suggest me correction or suggestion about Where could I have gone wrong or what have I missed in C code?.
#include "xil_printf.h"
#include "xil_io.h"
#include "xparameters.h"
#include "xil_types.h"
#include "xparameters_ps.h"
#include <stdio.h>
//Definitions for peripheral MYIPINETHREE_0 //
#define XPAR_ MYIPINETHREE_0_DEVICE_ID 0
#define XPAR_ MYIPINETHREE_0_S00_AXI_BASEADDR 0x43C00000
#define XPAR_ MYIPINETHREE_0_S00_AXI_HIGHADDR 0x43C0FFFF
int main(){
u32 baseaddr;
int sine, sinephase, enable,reg ;
while (1)
{
xil_printf("start of ip test\r");
if (enable == 1)
reg = 0xFFFFFFFF;
else
reg = 0x00000000;
Xil_Out32(0x43C00000, 32 );
sine = Xil_In32(baseaddr+4);
xil_printf("\r state: %d", sine);
Xil_Out32(0x43C00000, 32);
sinephase = Xil_In32(baseaddr+4);
xil_printf("\r state: %d", sinephase);
return 0;
}
}
To start with: you never initialize baseaddr but use it to read from.
Also I can't say because I have no idea how to verify that your addresses are correct. Normally you should use the defines from your xparameters.h file where the Xilinx board package program puts them. I don't see that happening here.
I am somewhat suspicious as all my Xilinx AXI addresses start with 0x800... but then I might be because I am using a different FPGA.
Please add a board layout or some additional information. You should use the addresses from xparameters.hinstead of hard coding them into your source code. The address space depends on your AXI master interface.

Creating File in arduino's Memory while arduino is operating

In my arduino project i have to store some integers(25 to be specific) in a file in arduino's memory (as i have arduino UNO and it doesn't have built-in port for SD Card) and read that file next-time i start the arduino .
Also my arduino is not connected to PC or laptop so i can't use file system of PC or laptop
so is there any way possible doing it ?
Arduino Uno has 1KB of non-volatile EEPROM memory, which you can use for this purpose. An integer is 2 bytes, so you should be able to store over 500 ints this way.
This example sketch should write a couple of integers from 10 to 5 into EEPROM memory:
#include <EEPROM.h>
void setup() {
int address = 0; //Location we want the data to be put.
for (int value = 10; value >= 5; --value)
{
// Write the int at address
EEPROM.put(eeAddress, value)
// Move the address, so the next value will be written after the first.
address += sizeof(int);
}
}
void loop() {
}
This example is a stripped down version of the one in the EEPROM.put documentation. Other examples can be found in the documentation of the various EEPROM functions.
Another nice tutorial on the subject can be found on tronixstuff.
By the way, if you need more memory, you could also use EEPROM memory banks. These are small ICs. They are available for very low prices in low amounts of memory, typically from 1KB to 256KB. Not much in terms of modern computing, but a huge expansion compared to the 1KB you have by default.

CPU write value passed from application to qemu is strange

I was trying to run RTEMS(a real-time OS) application on a sparc virtual machine using QEMU.
I'm almost there and I've seen it working hours ago. But after removing some prints it is not working and later I found it's not because of the removed prints. The data is not being passed correctly between the RTEMS image and the QEMU emulation model.(I'm working with QEMU version 1.5.50 and lan9118.c model borrowed from QEMU version 2.0.0. I modifed lan9118 a little.)
In the QEMU model, the memory region ops are defined as
struct MemoryRegionOps {
/* Read from the memory region. #addr is relative to #mr; #size is
* in bytes. */
uint64_t (*read)(void *opaque,
hwaddr addr,
unsigned size);
/* Write to the memory region. #addr is relative to #mr; #size is
* in bytes. */
void (*write)(void *opaque,
hwaddr addr,
uint64_t data,
unsigned size);
...
}
and in the RTEMS application, I write to the device like
*TX_FIFO_PORT = cmdA;
*TX_FIFO_PORT = cmdB;
where TX_FIFO_PORT is defined as below.
#define TX_FIFO_PORT (volatile ulong *)(SMSC9118_BASE + 0x20)
But when I write, for example,
cmdA : 0x2a300200 and cmdB : 0x2a002a00,
The values I expected are
cmdA : 0x0002302a and cmdB : 0x002a002a. (Just endian converted values)
But the values I see at the write function (entrance of QEMU) are
cmdA : 0x02000200 and cmdB : 0x2a002a00 respectively.
The observed values have not been endian converted and even the first value is different(lower 16 bit repeated).
What could be problem?
Any hint will be deeply appreciated.
Strangely I fixed this by commenting out the endian conversion for cmdA and cmdB in the RTEMS before writing to the device.(It was ok with the endian conversion..I don't know) So it's working 'almost'.
Anyway, here is a tip about exchaning CPU write/read data in QEMU processor and deivce.
In QEMU, Each device model provides write and read function, also it specifies how the word should be transferd to/from the device regarding endianness. It is specified like below.
static const MemoryRegionOps lan9118_mem_ops = {
.read = lan9118_readl,
.write = lan9118_writel,
.endianness = DEVICE_NATIVE_ENDIAN,
};
Here is the copy from email I received from Peter Maydell from qemu-discuss#nongnu.org mailing list.
------------------------
This depends on what the MemoryRegionOps struct for the memory region sets its .endianness field to.
DEVICE_NATIVE_ENDIAN means the device sees values the same way round as the guest CPU's native endianness[*], so if the guest does a 32 bit write of 0x12345678 then it appears in the write function's argument as 0x12345678. DEVICE_BIG_ENDIAN means that if the CPU is little endian then the word will be byteswapped.
DEVICE_LITTLE_ENDIAN means that if the CPU is big endian then the word will be byteswapped. The latter are useful for devices or buses which have a specific endianness which is not the same as that of the CPU (eg PCI is always little endian).

Writing ARM machine instructions and executing them from C (On the Raspberry pi)

I'm trying to write some self modifying code in C and ARM. I previously asked a similar question about MIPS and am now trying to port over the project to ARM.
My system := Raspbian on raspberry pi, ARMv6, GCC
There are a few things I am unsure of:
Does ARM require a D-cache write-back/I-cache invalidate (cache flush)? If so, how can we do this?
Also I tried an example
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int inc(int x){ //increments x
uint16_t *ret = malloc(2 * sizeof(uint16_t));
*(ret + 0) = 0x3001; //add r0 1 := r0 += 1
*(ret + 1) = 0x4770; //bx lr := jump back to inc()
int(*f)(int) = (int (*)(int)) ret;
return (*f)(x);
}
int main(){
printf("%d",inc(6)); //expect '7' to be printed
exit(0);}
but I keep getting a segmentation fault. I'm using the aapcs calling convention, which I've been given to understand is the default for all ARM
I'd be much obliged if someone pointed me in the right direction
Bonus question (meaning, it doesn't really have to be answered, but would be cool to know) - I "come from a MIPS background", how the heck do ARM programmers do without a 0 register? (as in, a register hardcoded to the value 0)
Read Caches and Self-Modifying Code on blogs.arm.com. Article includes an example as well which does what you are describing.
To answer your question from article
... the ARM architecture is often considered to be a Modified Harvard Architecture. ...
The typical drawback of a pure Harvard architecture is that instruction memory is not directly accessible from the same address space as data memory, though this restriction does not apply to ARM. On ARM, you can write instructions into memory, but because the D-cache and I-cache are not coherent, the newly-written instructions might be masked by the existing contents of the I-cache, causing the processor to execute old (or possibly invalid) instructions.
See __clear_cache for how to invalidate cache(s).
I hope you are also aware of ARM/Thumb instruction sets, if you are planning to push your instructions into memory.
Ok, so this works on my raspberry Pi.
#include <stdio.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stdlib.h>
int inc(int x){ //increments x
uint32_t *ret = mmap(NULL,
2 * sizeof(uint32_t), // Space for 16 instructions. (More than enough.)
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,0);
if (ret == MAP_FAILED) {
printf("Could not mmap a memory buffer with the proper permissions.\n");
return -1;
}
*(ret + 0) = 0xE2800001; //add r0 r0 #1 := r0 += 1
*(ret + 1) = 0xE12FFF1E; //bx lr := jump back to inc()
__clear_cache((char*) ret, (char*) (ret+2));
int(*f)(int) = (int (*)(int)) ret;
return (*f)(x);
}
int main(){
printf("%d\n",inc(6)); //expect '7' to be printed
exit(0);}
There are a couple of problems.
You don't flush your D-Cache and I-Cache, so most times the I-Cache will fetch stale data from L2. Under linux there is a libc/sys-call which does that for you. Either use __clear_cache(begin, end) or _builtin_clear_cache(begin, end).
You output Thumb-Code, but you don't take care of how your code gets called. The easiest way to fix that would be to use some asm-code to do the actual blx call and OR the address with 1, as this bit sets the mode the processor runs in. As you're malloc address will always be aligned to a word boundary, making you call thumb-code in arm-mode.

Resources