Modbus register adress space not linear? - memory

I'm currently developing a modbus server to control a device.
The device manual says about holding registers:
Adress 6000: ValueA, 2 Byte
Adress 6001: ValueB, 1 Byte; ValueC, 4 Byte; ValueD, 4 Byte
Adress 6005: ValueE, 2 Byte
The only supported read function is FC 03 / Read Multiple Holding Registers
To my knowledge, one can see the register as a memory block of numbered 16Bit values, and could read it in one go by reading 6 registers / 12 Byte beginning at 6000.
I think the 1Byte-value isn't an issue, the register simply contains a value not exceeding 255.
But expanding the table above gives:
Adress 6000: ValueA, 2 Byte
Adress 6001: ValueB, 1 Byte
Adress 6002-6003: ValueC, 4 Byte
Adress 6004-6005: ValueD, 4 Byte
Adress 6005: ValueE, 2 Byte
so, there is an overlap last line at 6005.
My device manual is full of such occurences, and meanwhile, I'm thinking that modbus registers ain't such a simple, linear memory as I thought.
Does anybody know if modbus registers are linear, or not?

I stumbled across a similar situation and asked about it in a more specialized forum. The "to long, didn`t read" was, that the address space is linear most of the time, but not always.
Check out the following example:
Excuse the German parts, but what you can see here, is that register address 0x2021 holds data made up of eight words or eight 16-bit blocks. Following your above logic you would expect the second word to be stored in the register 0x2022, but I checked on my local device and they are not the same. So, in summary, there are some devices out there which decide, that they give one register more memory than it's ought to have. So, register 0x2021 really holds 8 words on his own and does not use register 0x2022 to hold memory.
you might have a similar case.

Related

how Byte Address memory in Altera FPGA?

I worked with megafunctions to generate 32bit data memory in the fpga.but the output was addressed 32bit (4 bytes) at time , how to do 1 byte addressing ?
i have Altera Cyclone IV ep4ce6e22c8.
I'm designing a 32bit CPU in fpga ,
Nowadays every CPU address bus works in bytes. Thus to access your 32-bit wide memory you should NOT connect the LS 2 address bits. You can use the A[1:0] address bits to select a byte (or half word using A[1] only) from the memory when your read.
You still will need four byte write enable signals. This allows you to write word, half-words or bytes.
Have a look at existing CPU buses or existing connection standards like AHB or AXI.
Post edit:
but reading address 0001 , i get 0x05060708 but the desired value is 0x02030405.
What you are trying to do is read a word from a non-aligned address. There is no existing 32-bit wide memory that supports that. I suggest you have a look at how a 32-bit wide memory works.
The old Motorola 68020 architecture supported that. It requires a special memory controller which first reads the data from address 0 and then from address 4 and re-combines the data into a new 32-bit word.
With the cost of memory dropping and reducing CPU cycles becoming more important, no modern CPU supports that. They throw an exception: non-aligned memory access.
You have several choices:
Build a special memory controller which supports unaligned accesses.
Adjust your expectations.
I would go for the latter. In general it is based on the wrong idea how a memory works. As consolidation: You are not the first person on this website who thinks that is how you read words from memory.

What happens when memory "wraps" on an IA-32 supporting machine?

I'm creating a 64-bit model of IA-32 and am representing memory as a 0-based array of 2**64 bytes (the language I'm modeling this in uses ** as the exponentiation operator). This means that valid indices into the array are from 0 to 2**64-1. Now, to model the possible modes of accessing that memory, one can treat one element as an 8-bit number, two elements as a (little-endian) 16-bit number, etc.
My question is, what should my model do if they ask for a 16-bit (or 32-bit, etc.) number from location 2**64-1? Right now, what the model does is say that the returned value is Memory(2**64-1) + (8 * Memory(0)). I'm not updating any flags (which feels wrong). Is wrapping like this the correct behavior? Should I be setting any flags when the wrapping happens?
I have a copy of Intel-64-ia-32-ISA.pdf which I'm using as a reference, but it's 1,479 pages, and I'm having a hard time finding the answer to this particular question.
The answer is in Volume 3A, section 5.3: "Limit checking."
For ia-32:
When the effective limit is FFFFFFFFH (4 GBytes), these accesses [which extend beyond the end of the segment] may or may not cause the indicated exceptions. Behavior is implementation-specific and may vary from one execution to another.
For ia-64:
In 64-bit mode, the processor does not perform rumtime limit checking on code or data segments. Howver, the processor does check descriptor-table limits.
I tested it (did anyone expect that?) for 64bit numbers with this code:
mov dword [0], 0xDEADBEEF
mov dword [-4], 0x01020304
mov rdi, [-4]
call writelonghex
In a custom OS, with pages mapped as appropriate, running in VirtualBox. writelonghex just writes rdi to the screen as a 16-digit hexadecimal number. The result:
So yes, it does just wrap. Nothing funny happens.
No flags should be affected (though the manual doesn't say that no flags should be set for address wrapping, it does say that mov reg, [mem] doesn't affect them ever, and that includes this case), and no interrupt/trap/whatever happens (unless of course one or both pages touched are not present).

Referencing a word in memory vs referencing a memory cell?

Well i probably could have asked the professor about this, but i haven't been going to faculty very often in the past few weeks so i'll ask anyone who comes across this.
In MIPS if an the starting address of an array of integers (the address of A[0]) is stored in the register $s3 then the assembler code for storing the 9th element of the array in the temporary register $t0 will be lw $t0 32($s3). So the offset is 32. The explanation for this is that most architectures today reference every byte in memory(i.e. every memory cell) and since an integer is 4 bytes which is the most common size of a "word" the address for the next integer in memory would be the current address + 4 , making address for 9th integer: starting address + 4*8. Nice!
Now i know that for a character encoded in ASCII the number of bits needed is 8 = 1 byte. So what i want to ask is if we have an array of chars will it be the case that the next character's address in the array is: "the current address + 1" since for chat only 1 memory cell is needed and every memory cell has its own address? Or, because the word size in the architecture is 4 bytes, the smallest amount that can be referenced is a word although every memory cell has its own address, making the character take 4 byes despite only needing 1? If the first case if true how would the processor know weather to add 1 to the address of 4? Wouldn't it be needed for an additional instruction being made by the compiler for determining the data type? Also, cause the int took the space referenced by 4 addresses, is the address which the processor uses to load the integer that of the first byte or?
Now i'm on cache memory(by the way i'm learning from Patterson and Hennessy's Computer organization and design) and this thing really bothers me so i would be grateful if someone
would answer. So, thanks!
if we have an array of chars will it be the case that the next character's address in the array is: "the current address + 1 [byte]" ?
Yes.
If [this] is true how would the processor know weather to add 1 to the address of 4? Wouldn't it be needed for an additional instruction being made by the compiler for determining the data type?
There are additional instructions. lw is used for loading words, while lb/lbu is used for loading bytes. But that only affects the size of the data to load. The offsets aren't scaled according to the data size like they are in C. If you use an offset of 3 for an lw it will try to load from the address given by the base register + 3 bytes.
Also, cause the int took the space referenced by 4 addresses, is the address which the processor uses to load the integer that of the first byte or?
Yes. And the layout of the word value in memory depends on the endianness of the CPU. The value 0x12345678 on a little-endian system would be stored as:
-- address -->
78 56 34 12
and on a big-endian system it would be stored as:
-- address -->
12 34 56 78

Why are memory addresses incremented by 4 in MIPS?

If something is stored at 0x1001 0000 the next thing is stored at 0x1001 0004. And if I'm correct the memory pieces in a 32-bit architecture are 32 bits each. So would 0x1001 0002 point to the second half of the 32 bits?
First of all, memory addresses in MIPS architecture are not incremented by 4. MIPS uses byte addressing, so you can address any byte from memory (see e.g. lb and lbu to read a single byte, lh and lhu to read a half-word).
The fact is that if you read words which are 32 bits length (4 bytes, lw), then two consecutive words will be 4 bytes away from each other. In this case, you would add 4 to the address of the first word to get the address of the next word.
Beside this, if you read words you have to align them in multiples of 4, otherwise you will get an alignment exception.
In your example, if the first word is stored in 0x10010000 then the next word will be in 0x10010004 and of course the first half/second half would be in 0x1001000 and 0x1001002 (the ordering will depend on the endianness of the architecture).
You seem to have answered this one yourself! 32 bits make 4 bytes, so if you're e.g. pushing to a stack, where all elements are pushed as the same size, each next item will be 4 bytes ahead (or before) the next.

Difference between word addressable and byte addressable

Can someone explain what's the different between Word and Byte addressable? How is it related to memory size etc.?
A byte is a memory unit for storage
A memory chip is full of such bytes.
Memory units are addressable. That is the only way we can use memory.
In reality, memory is only byte addressable. It means:
A binary address always points to a single byte only.
A word is just a group of bytes – 2, 4, 8 depending upon the data bus size of the CPU.
To understand the memory operation fully, you must be familiar with the various registers of the CPU and the memory ports of the RAM. I assume you know their meaning:
MAR(memory address register)
MDR(memory data register)
PC(program counter register)
MBR(memory buffer register)
RAM has two kinds of memory ports:
32-bits for data/addresses
8-bit for OPCODE.
Suppose CPU wants to read a word (say 4 bytes) from the address xyz onwards. CPU would put the address on the MAR, sends a memory read signal to the memory controller chip. On receiving the address and read signal, memory controller would connect the data bus to 32-bit port and 4 bytes starting from the address xyz would flow out of the port to the MDR.
If the CPU wants to fetch the next instruction, it would put the address onto the PC register and sends a fetch signal to the memory controller. On receiving the address and fetch signal, memory controller would connect the data bus to 8-bit port and a single byte long opcode located at the address received would flow out of the RAM into the CPU's MDR.
So that is what it means when we say a certain register is memory addressable or byte addressable. Now what will happen when you put, say decimal 2 in binary on the MAR with an intention to read the word 2, not (byte no 2)?
Word no 2 means bytes 4, 5, 6, 7 for 32-bit machine. In real physical memory is byte addressable only. So there is a trick to handle word addressing.
When MAR is placed on the address bus, its 32-bits do not map onto the 32 address lines(0-31 respectively). Instead, MAR bit 0 is wired to address bus line 2, MAR bit 1 is wired to address bus line 3 and so on. The upper 2 bits of MAR are discarded since they are only needed for word addresses above 2^32 none of which are legal for our 32 bit machine.
Using this mapping, when MAR is 1, address 4 is put on the bus, when MAR is 2, address 8 is put on the bus and so forth.
It is a bit difficult in the beginning to understand. I learnt it from Andrew Tanenbaums's structured computer organisation.
This image should make it easy to understand:
http://i.stack.imgur.com/rpB7N.png
Simply put,
• In the byte addressing scheme, the first word starts at address 0, and
the second word starts at address 4.
• In the word addressing scheme, all bytes of the first word are located
in address 0, and all bytes of the second word are located in address 1.
The advantage of byte-addressability are clear when we consider applications that process data one byte at a time. Access of a single byte in a byte-addressable system requires only the issuing of a single address. In a 16–bit word addressable system, it is necessary first to compute the address of the word containing the byte, fetch that word, and then extract the byte from the two-byte word. Although the processes for byte extraction are well understood, they are less efficient than directly accessing the byte. For this reason, many modern machines are byte addressable.
Addressability is the size of a unit of memory that has its own address. It's also the smallest chunk of memory that you can modify without affecting its neighbours.
For example: a machine where bytes are the normal 8 bits, and the word-size = 4 bytes. If it's a word-addressable machine, there's no such thing as the address of the second byte of an int. Dealing with strings (e.g. an array like char str[]) becomes inconvenient, because you still store characters packed together. Modifying just str[1] means loading the word that contains it, doing some shift/and/or operations to apply the change, then doing a word store.
Note that this is different from a machine that doesn't allow unaligned word load/stores (where the low 2 bits of a word address have to be 0). Such machines usually have a byte load/store instruction. We're talking about machines without even that.
CPU addresses might actually still include the low bits, but require them to always be zero (or ignore them). However, after checking that they're zero, the could be discarded, so the rest of the memory system only sees the word address, where two adjacent words have an address that differs by 1 (not 4). However, on a 16-bit CPU where a register can only hold 64k different addresses, you wouldn't likely do this. Each separate CPU address would refer to a different 2 bytes of memory, instead of discarding the low bit. 2B word-addressable memory would let you address 128kiB of memory, instead of just 64kiB with byte-addressable memory.
Fun fact: ARM used to use the low 2 bits of an address as a shuffle control for unaligned word loads. (But it always had byte load/store instructions.)
See also:
https://en.wikipedia.org/wiki/Word-addressable
https://en.wikipedia.org/wiki/Byte_addressing
Note that bit-addressable memory could exist, but doesn't. 8-bit bytes are nearly universally standard now. (Ancient computers sometimes had larger bytes, see the history section of wikipedia's Byte article.)

Resources