Where is ARM's (LPC18xx's) shadow pointer - arm

I am working with an NXP LPX1837.
User manual UM10430, sec 4.3 talks about
The LPC 18xx contains a shadow pointer that allows areas of memory to be mapped to address 0x0.
and
set ARM's shadow pointer
I want to utilize this shadow pointer. But I can't find further informations for that. Can anyone give me a hint, where i can find more details / spec about this shadow pointer?
Is it really an ARM feature or specific to LPC18xx?
Thx
Manuel

To answer my own questiong:
Shadow pointer is in
CREG->M3MEMMAP
Shadow address when accessing memory at
address 0x00000000 + X.
All memory mapped addresses must be located on a 4 kB boundary.

Related

Big empty space in memory?

Im very new to embedded programming started yesterday actually and Ive noticed something I think is strange. I have a very simple program doing nothing but return 0.
int main() {
return 0;
}
When I run this in IAR Embedded Workbench I have a memory view showing me the programs memory. Ive noticed that in the memory there is some memory but then it is a big block of empty space and then there is memory again (I suck at explaining :P so here is an image of the memory)
Please help me understand this a little more than I do now. I dont really know what to search for because Im so new to this.
The first two lines are the 8 interrupt vectors, expressed as 32-bit instructions with the highest byte last. That is, read them in groups of 4 bytes, with the highest byte last, and then convert to an instruction via the usual method. The first few vectors, including the reset at memory location 0, turn out to be LDR instructions, which load an immediate address into the PC register. This causes the processor to jump to that address. (The reset vector is also the first instruction to run when the device is switched on.)
You can see the structure of an LDR instruction here, or at many other places via an internet search. If we write the reset vector 18 f0 95 e5 as e5 95 f0 18, then we see that the PC register is loaded with the address located at an offset of 0x20.
So the next two lines are memory locations referred to by instructions in the first two lines. The reset vector sends the PC to 0x00000080, which is where the C runtime of your program starts. (The other vectors send the PC to 0x00000170 near the end of your program. What this instruction is is left to the reader.)
Typically, the C runtime is code added to the front of your program that loads the global variables into RAM from flash, and sets the uninitialized RAM to 0. Your program starts after that.
Your original question was: why have such a big gap of unused flash? The answer is that flash memory is not really at a premium, so we can waste a little, and that having extra space there allows for forward-compatibility. If we need to increase the vector table size, then we don't need to move the code around. In fact, this interrupt model has been changed in the new ARM Cortex processors anyway.
Physical (not virtual) memory addresses map to physical circuits. The lowest addresses often map to registers, not RAM arrays. In the interest of consistency, a given address usually maps to the same functionality on different processors of the same family, and missing functionality appears as a small hole in the address mapping.
Furthermore, RAM is assigned to a contiguous address range, after all the I/O registers and housekeeping functions. This produces a big hole between all the registers and the RAM.
Alternately, as #Martin suggests, it may represent uninitialized and read-only Flash memory as -- bytes. Unlike truly unassigned addresses, access to this is unlikely to produce an exception, and you might even be able to make them "reappear" using appropriate Flash controller commands.
On a modern desktop-class machine, virtual memory hides all this from you, and even parts of the physical address map may be configurable. Many embedded-class processors allow configuration to the extent of specifying the location of the interrupt vector table.
UncleO is right but here is some additional information.
The project's linker command file (*.icf for IAR EW) determines where sections are located in memory. (Look under Project->Options->Linker->Config to identify your linker configuration file.) If you view the linker command file with a text editor you may be able to identify where it locates a section named .intvec (or similar) at address 0x00000000. And then it may locate another section (maybe .text) at address 0x00000080.
You can also see these memory sections identified in the .map file, along with their locations. (Ensure "Generate linker map file" is checked under Project->Options->Linker->List.) The map file is an output from the build, however, and it's the linker command file that determines the locations.
So that space in memory is there because the linker command file instructed it to be that way. I'm not sure whether that space is necessary but it's certainly not a problem. You might be able to experiment with the linker command file and move that second section around. But the exception table (a.k.a. interrupt vector table) must be located at 0x00000000. And you'll want to ensure that the reset vector points to the new location of the startup code if you move it.

What memory addresses are available for use?

How do i find out what memory addresses are suitable for use ?
More specifically, the example of How to use a specific address is here: Pointer to a specific fixed address, but not information on Why this is a valid address for reading/writing.
I would like a way of finding out that addresses x to y are useable.
This is so i can do something similar to memory mapped IO without a specific simulator. (My linked Question relevant so i can use one set of addresses for testing on Ubuntu, and another for the actual software-on-chip)
Ubuntu specific answers please.
You can use whatever memory address malloc() returns. Moreover, you can specify how much memory you need. And with realloc() you even can change your mind afterwards.
You're mixing two independent topics here. The Question that you're linking to, is regarding a micro controller's memory mapped IO. It's referring to the ATM128, a Microcontroller from the Atmel. The OP of that question is trying to write to one of the registers of it, these registers are given specific addresses.
If you're trying to write to the address of a register, you need to understand how memory mapped IO works, you need to read the spec for the chipset/IC your working on. Asking this talking about "Ubuntu specific answers" is meaningless.
Your program running on the Ubuntu OS is running it it's own virtual address space. So asking if addresses x to y are available for use is pretty pointless... unless you're accessing hardware, there's no point in looking for a specific address, just use what the OS gives you and you'll know you're good.
Based on your edit, the fact that you're trying to do a simulation of memory mapped IO, you could do something like:
#ifdef SIMULATION
unsigned int TX_BUF_REG; // The "simulated" 32-bit register
#else
#define TX_BUF_REG 0x123456 // The actual address of the reg you're simulating
#endif
Then use accessor macro's to read or write specific bits via a mask (as is typically done):
#define WRITE_REG_BITS(reg, bits) {reg |= bits;}
...
WRITE_REG_BITS(TX_BUF_REG, SOME_MASK);
Static variables can be used in simulations this way so you don't have to worry about what addresses are "safe" to write to.
For the referenced ATMega128 microcontroller you look in the Datasheet to see which addresses are mapped to registers. On a PC with OS installed you won't have a chance to access hardware registers directly this way. At least not from userspace. Normally only device drivers (ring 0) are allowed to access hardware.
As already mentioned by others you have to use e.g. malloc() to tell the OS that you need a pointer to memory chuck that you are allowed to write to. This is because the OS manages the memory for the whole system.

C code, why is address 0xFF00 being cast to a struct?

I am trying to understand some Linux kernel driver code written in C for a USB Wi-Fi adapter. Line 1456 in file /drivers/net/wireless/rtl818x/rtl8187/dev.c (just in case anyone wanted to refer to the kernel code for context) reads:
priv->map = (struct rtl818x_csr *)0xFF00;
I am curious about what exactly the right operand is doing here - (struct rtl818x_csr *)0xFF00;. I have been interpreting this as saying "cast memory address 0xFF00 to be of type rtl818x_csr and then assign it to priv->map". If my interpretation is correct, what is so special about memory address 0xFF00 that the driver can reliably tell that what it is after will always be at this address? The other thing I am curious about is that 0xFF00 is only 16-bits. I would be expecting 32/64-bits if it were casting a memory address.
Can anyone clarify exactly what is going on in this line of code? I imagine there's a flaw in my understanding of the C syntax.
0xFF00 is an address in the IO address space of the system. If you look in the code, the address is never directly dereferenced but accessed through IO functions.
For example, in the call
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD,
RTL818X_EEPROM_CMD_CONFIG);
which then calls Linux kernel low level IO functions.
The address is cast to a pointer to a struct to give access to offsets from the adress, example here:
0xFF00 + offsetof(struct rtl818x_csr, EEPROM_CMD)
Note that in the rtl818x_iowrite8 call above, no dereference occurs when passing the &priv->map->EEPROM_CMD argument because of the & operator, only the address + offset is computed. The dereference is further achieved withtin the internal low level functions called inside rtl818x_iowrite8.
Casting an absolute address to a pointer to a structure is a common way in drivers to access the (memory mapped) registers of a device as a normal C structure.
Using 0xff00 works because C doesn't do sign extension of numbers.
You have to consider this from the device point of view.
Starting at address 0xFF00 inside the address space mapped for the rtl8187 device is a memory range that holds information structured the same way as the rtl818x_csr struct defined here.
So after you logically map that region you can start doing bus reads and writes on it to control the device. Like here (had to cut two more hyperlinks because I don't have the reputation necessary to post more than 3, but you get the point). These are just a couple of examples. If you read the entire file you'll see reads and writes are sprinkled everywhere.
In order to understand why that structure looks that way and why 0xFF00 is used instead of 0xBEEF or 0xDEAD you'll have to consult the datasheet for that device.
So if you want to start looking at kernel code, and specially device drivers, you'll have to have more than just the code. You'll need the datasheet or specifications as well. This can be rather difficult to find (see the gazillions of email threads and articles soliciting open documentation from the vendors).
Anyway, I hope I answered your question.
Happy hacking!

Dereferencing a pointer at lower level in C

When malloc returns a pointer (a virtual address of a block of data),
char *p = malloc (10);
p has a virtual address, (say x). And p holds a virtual address of a block of 10 addresses.
Say these virtual addresses are from y to y+10.
These 10 addresses belong to a page , and the virtual --> physical mapping is placed in the page table.
When processor dereferences the pointer p, say printf("%c", *p); , how does the processor know that it has to access the address at y ?
Is the page table accessed twice in order to dereference a pointer ,in other words -print the address pointed by p ? How exactly is it done, can anybody explain ?
Also, for accessing stack variables, does the processor have to access it through page table ?
Isn't the stack pointer register (SP) not pointing to the stack already ?
I think there's a muddling of different layers.
First, page tables: This is a data structure that uses some memory to provide pointers to more memory. Given a particular virtual address, it can deconstruct it into indices into the table. Right now, this is happening under the cover in the kernel, but it's possible to implement this same idea in user space.
Now, the next step is processes. Each process gets its own view of memory and hence has its one set of page tables. How the processor know where these different page tables reside? In a special control register called cr3. Changing processes is sometimes called a context switch; and rightly so because setting cr3 changes the processes view of virtual memory.
But the next question is, how does the processor even understand the concept of virtual memory? Well, in some older architectures (MIPs comes to mind), the system would keep a cache of recently translated memory and provides guidance for how to handle virtual memory access. In x86, the cache (more commonly called a translation lookaside buffer) is actually implemented in hardware. The processor stores these translations so it can handle the page table lookups automatically. If there's a cache miss, then it will actually traverse the page table structure as set up by the OS to lookup what it should reference.
Of course, this means there must be at least two different modes for the processor: one that assumes the addresses are direct and one that traverses the page tables. The first mode, real mode, is there on boot and only around long enough to set up the tables before the bootloader turns on virtual mode and jumps to the beginning of the rest of the code.
The short answer to my long explanation is that in all likelihood, the page tables aren't accessed at all because the processor already has the address translations.
And p holds a virtual address of a block of 10 addresses.
You're confused. p is a pointer holding the address of a 10-byte block; how these bytes are interpreted is up to the application.

What is the difference between far pointers and near pointers?

Can anybody tell me the difference between far pointers and near pointers in C?
On a 16-bit x86 segmented memory architecture, four registers are used to refer to the respective segments:
DS → data segment
CS → code segment
SS → stack segment
ES → extra segment
A logical address on this architecture is written segment:offset. Now to answer the question:
Near pointers refer (as an offset) to the current segment.
Far pointers use segment info and an offset to point across segments. So, to use them, DS or CS must be changed to the specified value, the memory will be dereferenced and then the original value of DS/CS restored. Note that pointer arithmetic on them doesn't modify the segment portion of the pointer, so overflowing the offset will just wrap it around.
And then there are huge pointers, which are normalized to have the highest possible segment for a given address (contrary to far pointers).
On 32-bit and 64-bit architectures, memory models are using segments differently, or not at all.
Since nobody mentioned DOS, lets forget about old DOS PC computers and look at this from a generic point-of-view. Then, very simplified, it goes like this:
Any CPU has a data bus, which is the maximum amount of data the CPU can process in one single instruction, i.e equal to the size of its registers. The data bus width is expressed in bits: 8 bits, or 16 bits, or 64 bits etc. This is where the term "64 bit CPU" comes from - it refers to the data bus.
Any CPU has an address bus, also with a certain bus width expressed in bits. Any memory cell in your computer that the CPU can access directly has an unique address. The address bus is large enough to cover all the addressable memory you have.
For example, if a computer has 65536 bytes of addressable memory, you can cover these with a 16 bit address bus, 2^16 = 65536.
Most often, but not always, the data bus width is as wide as the address bus width. It is nice if they are of the same size, as it keeps both the CPU instruction set and the programs written for it clearer. If the CPU needs to calculate an address, it is convenient if that address is small enough to fit inside the CPU registers (often called index registers when it comes to addresses).
The non-standard keywords far and near are used to describe pointers on systems where you need to address memory beyond the normal CPU address bus width.
For example, it might be convenient for a CPU with 16 bit data bus to also have a 16 bit address bus. But the same computer may also need more than 2^16 = 65536 bytes = 64kB of addressable memory.
The CPU will then typically have special instructions (that are slightly slower) which allows it to address memory beyond those 64kb. For example, the CPU can divide its large memory into n pages (also sometimes called banks, segments and other such terms, that could mean a different thing from one CPU to another), where every page is 64kB. It will then have a "page" register which has to be set first, before addressing that extended memory. Similarly, it will have special instructions when calling/returning from sub routines in extended memory.
In order for a C compiler to generate the correct CPU instructions when dealing with such extended memory, the non-standard near and far keywords were invented. Non-standard as in they aren't specified by the C standard, but they are de facto industry standard and almost every compiler supports them in some manner.
far refers to memory located in extended memory, beyond the width of the address bus. Since it refers to addresses, most often you use it when declaring pointers. For example: int * far x; means "give me a pointer that points to extended memory". And the compiler will then know that it should generate the special instructions needed to access such memory. Similarly, function pointers that use far will generate special instructions to jump to/return from extended memory. If you didn't use far then you would get a pointer to the normal, addressable memory, and you'd end up pointing at something entirely different.
near is mainly included for consistency with far; it refers to anything in the addressable memory as is equivalent to a regular pointer. So it is mainly a useless keyword, save for some rare cases where you want to ensure that code is placed inside the standard addressable memory. You could then explicitly label something as near. The most typical case is low-level hardware programming where you write interrupt service routines. They are called by hardware from an interrupt vector with a fixed width, which is the same as the address bus width. Meaning that the interrupt service routine must be in the standard addressable memory.
The most famous use of far and near is perhaps the mentioned old MS DOS PC, which is nowadays regarded as quite ancient and therefore of mild interest.
But these keywords exist on more modern CPUs too! Most notably in embedded systems where they exist for pretty much every 8 and 16 bit microcontroller family on the market, as those microcontrollers typically have an address bus width of 16 bits, but sometimes more than 64kB memory.
Whenever you have a CPU where you need to address memory beyond the address bus width, you will have the need of far and near. Generally, such solutions are frowned upon though, since it is quite a pain to program on them and always take the extended memory in account.
One of the main reasons why there was a push to develop the 64 bit PC, was actually that the 32 bit PCs had come to the point where their memory usage was starting to hit the address bus limit: they could only address 4GB of RAM. 2^32 = 4,29 billion bytes = 4GB. In order to enable the use of more RAM, the options were then either to resort to some burdensome extended memory solution like in the DOS days, or to expand the computers, including their address bus, to 64 bits.
Far and near pointers were used in old platforms like DOS.
I don't think they're relevant in modern platforms. But you can learn about them here and here (as pointed by other answers). Basically, a far pointer is a way to extend the addressable memory in a computer. I.E., address more than 64k of memory in a 16bit platform.
A pointer basically holds addresses. As we all know, Intel memory management is divided into 4 segments.
So when an address pointed to by a pointer is within the same segment, then it is a near pointer and therefore it requires only 2 bytes for offset.
On the other hand, when a pointer points to an address which is out of the segment (that means in another segment), then that pointer is a far pointer. It consist of 4 bytes: two for segment and two for offset.
Four registers are used to refer to four segments on the 16-bit x86 segmented memory architecture. DS (data segment), CS (code segment), SS (stack segment), and ES (extra segment). A logical address on this platform is written segment:offset, in hexadecimal.
Near pointers refer (as an offset) to the current segment.
Far pointers use segment info and an offset to point across segments. So, to use them, DS or CS must be changed to the specified value, the memory will be dereferenced and then the original value of DS/CS restored. Note that pointer arithmetic on them doesn't modify the segment portion of the pointer, so overflowing the offset will just wrap it around.
And then there are huge pointers, which are normalized to have the highest possible segment for a given address (contrary to far pointers).
On 32-bit and 64-bit architectures, memory models are using segments differently, or not at all.
Well in DOS it was kind of funny dealing with registers. And Segments. All about maximum counting capacities of RAM.
Today it is pretty much irrelevant. All you need to read is difference about virtual/user space and kernel.
Since win nt4 (when they stole ideas from *nix) microsoft programmers started to use what was called user/kernel memory spaces.
And avoided direct access to physical controllers since then. Since then dissapered a problem dealing with direct access to memory segments as well. - Everything became R/W through OS.
However if you insist on understanding and manipulating far/near pointers look at linux kernel source and how it works - you will newer come back I guess.
And if you still need to use CS (Code Segment)/DS (Data Segment) in DOS. Look at these:
https://en.wikipedia.org/wiki/Intel_Memory_Model
http://www.digitalmars.com/ctg/ctgMemoryModel.html
I would like to point out to perfect answer below.. from Lundin. I was too lazy to answer properly. Lundin gave very detailed and sensible explanation "thumbs up"!

Resources