ARM (SAMC) memory mapping - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: January 04, 2020, 12:50:09 pm
content: Looking at the datasheet for the SAMC range the addresses address individual bytes. Any 32 bit register is 4 addresses apart. Would this mean that an 8 bit variable would only use 8 bits of memory and not 32 bit?

author: Jeroen3
author_rank: Super Contributor
timestamp: January 04, 2020, 03:39:16 pm
content: InARMv6-mthe model is that bytes are addressable. But accessibility with byte width is not guaranteed.Bits are no longer addressable as with older 8 bit architectures. Unless your chip has bit-banding, of which the usability is debatable.However it may very well be required to read/write in full words (32 bits) or more in some regions.QuoteYes, of course 8 bits only use 8 bits of space.Were you under the impressions that the minimum addressable unit was 32 bit? Since that would complicate thingsa lot.edit:added link to armv6-m technical reference manual

author: Simon
author_rank: Unknown
timestamp: January 04, 2020, 04:05:20 pm
content: Quote from: Jeroen3 on January 04, 2020, 03:39:16 pmNot if the smallest addressable unit is bigger. This is like the fallacy of the Boolean variables in say Arduino. The variable is 8 bits even if it only needs one bit. GCC for AVR has as a minimum 8 bit variables.QuoteNo it would just mean that every variable would take up 32 bits which would be very inefficient for flag variables that only need 1 bit but with byte addressing is more efficient if not perfect for sub 8 bit variables. the premise of my question is that it looks like each address is for 8 bits not 32 at least on the registers. Presumably it's the same for the RAM as this is where it would make a real difference to code density.

author: andersm
author_rank: Super Contributor
timestamp: January 04, 2020, 05:08:23 pm
content: Quote from: Simon on January 04, 2020, 04:05:20 pmThe C language does not support a "bit" type. Compilers that do have it, use nonstandard extensions. You can use bitfields to pack flags, but they can produce rather inefficient code.

author: Simon
author_rank: Unknown
timestamp: January 04, 2020, 05:12:17 pm
content: well yes a byte variable that only needs one bit is faster to test for 0 or 1 than having to drag a bit out of a byte full. but the stand alone variable will mean 8 times the memory used.

author: Simon
author_rank: Unknown
timestamp: January 04, 2020, 05:24:44 pm
content: generally I just use 1 byte variables for flags but never had enough to worry about the memory used. Obviously on ARM it made sense to have the ability to address 1 byte at a time rather than every "word" or 1-16 bit variables would use 2 to 32 times the required memory space.

author: ataradov
author_rank: Super Contributor
timestamp: January 04, 2020, 07:01:13 pm
content: Quote from: Simon on January 04, 2020, 04:05:20 pmImagine addressing an array of bytes if this were the case. That would be a total nightmare and architecture would be basically dead, since none in their right mind would use it.

author: Simon
author_rank: Unknown
timestamp: January 04, 2020, 07:43:22 pm
content: which is what i thought but was just wondering

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 04, 2020, 07:49:24 pm
content: Couple things...* Regarding "booleans", a C compiler will usually not "pack" several variables together on its own, and the smallest variable in C has byte size. So booleans or not, the only standard way of doing this would be to use bit fields, as variables themselves can't be any smaller than a "byte". The resulting size of such a struct with bit fields may still be larger than what's strictly needed, and is often not any smaller than an 'int' - the size of which depends on the platform. It may also not be as efficient to access.* Regarding "bytes", this has been in a recent discussion about C. Yes the C standard doesn't actually guarantee that a "byte", which is pretty much defined as the same as a "char", is 8-bit. It' just the smallest usable size in C, and by definition, sizeof(char) is 1. sizeof() gives the size in bytes. Which again are not guaranteed to be 8-bit, but are implementation-defined.* Now there is at least one detail in C99 standards and later, that IMO can't make a byte, as defined in the C standard, anything else than 8-bit. Warning, the following ONLY applies to C99+, not earlier standard versions. The reasoning is as follows: a "byte" is the smallest size a variable can hold. With C99+, the introduction of <stdint.h> makes int8_t/uint8_t available (some of the intxx_t are optional, but I think int8_t/uint8_t is mandatory.) It follows that the smallest size, as defined as a "byte", can't be larger than an int8_t/uint8_t, which is guaranteed to be exactly 8 bits. So, only on platforms that don't support the int8_t/uint8_t types, there could be a chance that a "byte" is not 8-bit. If a platform/compiler supports them, then a "byte" can't possibly be anything else than this, as it would imply, for instance, that sizeof(int8_t) is smaller than 1, which is not possible.

author: Simon
author_rank: Unknown
timestamp: January 04, 2020, 07:54:27 pm
content: well as the address space seems to go every byte because all 32 bit registers have 4 bytes that can be individually addressed so clearly ARM addresses bytes although the data bus is 32 bit.I would have thought that a micro-controller compiler would be tightly optimised to it's architecture.

author: ataradov
author_rank: Super Contributor
timestamp: January 04, 2020, 07:55:47 pm
content: The bus is maximum 32-bits. There are size signals that indicate the desired transfer size.Also, fetching a byte directly is more efficient than fetching a word and extracting a byte from that.

author: newbrain
author_rank: Super Contributor
timestamp: January 04, 2020, 10:25:33 pm
content: Quote from: SiliconWizard edited by newbrain on January 04, 2020, 07:49:24 pmNo, they are not. All types instdint.hare optional:Quote from: ISO/IEC 9899, 7.18.1.1, §3So, no additional requirement on the architecture, as long as the minimum size requirement are fulfilled, i.e.(u)int9_tis a perfectly acceptable "byte".In C11, the typedefs are mandatory if 8, 16, 32, 64 -bits wide integers existand their representation is two's complement.No further changes in C18.

author: ataradov
author_rank: Super Contributor
timestamp: January 04, 2020, 10:43:57 pm
content: From a practical point of view it does not matter. The only platform that have 16-bit "byte" are some DSPs and those are dying and quickly become irrelevant. Plus coding for those in C was always stupid anyway.No one will make a processor with non-8-bit bytes.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 04, 2020, 10:57:21 pm
content: Quote from: newbrain on January 04, 2020, 10:25:33 pmOk, I thought they were, but wasn't entirely sure. Hence my cautious "I think". Just had to re-open the standard. Actually, the "int_least8_t" is the one that is required. Which makes sense.What this implies then, is that a "byte" cannot be less than 8-bit IMO, following the same reasoning as above.The rest of my post even more cautiously added: "So, only on platforms that don't support the int8_t/uint8_t types, there could be a chance that a "byte" is not 8-bit."Which I think is correct in this form.Quote from: newbrain on January 04, 2020, 10:25:33 pmIndeed. But we still have a problem of handling multiples of "bytes" for the sizeof operator to be consistent. If a byte was implemented as a 9-bit word, logically any type that would be of sizeof 2 would have to be double that at least, so on such a platform, I don't think exact 16-bit words could in turn exist.So take again my more cautious: "So, only on platforms that don't support the int8_t/uint8_t types, there could be a chance that a "byte" is not 8-bit."Everytime int8_t/uint8_t types would be defined, I think you can safely assume that a byte is exactly 8-bit.

author: westfw
author_rank: Super Contributor
timestamp: January 05, 2020, 12:08:25 am
content: QuoteBy "registers" here, presumably you mean "control registers for peripherals." The CPU registers r0..16 are NOT byte-addressable.You have to be a little bit careful. The Microchip SAMC datasheet says explicitly:QuoteBut I don't think that that's necessarily true of all ARM architecture chips; I'm pretty sure I've seen some that only support 32bit reads of certain registers. Maybe that was the core ARM peripherals (SysTick, NVIC, etc):QuoteI'm also not sure that you can always read multiple 8bit registers that happen to be adjacent...Note that while there is still cause to conserve memory itself, there is LOTS "address space" available, and most ARM microcontrollers are more than happy to scatter peripheral config/status info across "many" bytes worth of registers. many of which have unused ("reserved") bits. Sometimes the layout is convenient, sometimes not (especially with the CM0's limit on index/offset addressing.)

author: ataradov
author_rank: Super Contributor
timestamp: January 05, 2020, 12:17:18 am
content: Yes, majority of peripheral registers on MCUs are 32-bit access only. Majority of registers on 32-bit MCUs are 32 bit only, not that 8- and 16-bit garbage.The spreading happens naturally to save the resources on decoding logic. It is easier to decode big chunks of memory allocated to the peripherals. The peripheral then can use a few bits to decode the register within its chunk. The remaining bits may be left unconnected in decoders.The result would be the all peripheral registers are aliased over the big chunk. But even if you want to trap the incorrect access, it is still easier this way.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 05, 2020, 12:36:29 am
content: Indeed.And 32-bit address space is still gigantic enough for an MCU these days that you can largely afford to waste some of it (still a ridiculous amount compared to the 4GB available...)

author: Simon
author_rank: Unknown
timestamp: January 05, 2020, 10:06:40 am
content: what i was more interested in was that the addresses address 8 bits at a time so the smallest chunk of data handled is a byte so there is no point in having a variable smaller than a byte but as it does not address 4 bytes at a time it does not mean that 4 bytes of RAM have to be used no matter the size of variable.I find the 8/16 bit access to the peripheral config registers a bit confusing as generally i would write them all in one go and i am worried about the caveats like synchronised registers. Usually i work out what an entire register needs to be and do it in one write if I am setting up a peripheral. I suppose where there are only one bit in a register byte that can be read/written as a byte as there is nothing else to upset without the need for read-modify-write.

author: newbrain
author_rank: Super Contributor
timestamp: January 05, 2020, 04:34:39 pm
content: SiliconWizard, sorry if I was a bit dry in my note, but it was just meant to point out that the standard, as of today, still allows for "odd" architectures, not to contest your correctly phrased post.Quote from: SiliconWizard on January 04, 2020, 10:57:21 pmAgreed on all counts, with the minor nitpick (as it would seem I'm at it...) that the minimum bit size of "char" is clearly enforced in5.2.4.2.1 Sizes of integer types <limits.h>(C99), part of "Environmental limits", so the int_least8_t is a consequence:QuoteThis was already true in C89, before the introduction of (always be praised) stdint.h.Quote from: ataradov on January 05, 2020, 12:17:18 amEh...a vast majority, yes, unfortunately mixed with a lot of 16 bit legacy peripherals IPs even in modern and powerful MCUs (e.g. iMX RTxxxx and its PWM, TMR, ENC, mostly everything in MSP432 - lifted straight from MSP430? - etc. etc.).

author: Simon
author_rank: Unknown
timestamp: January 05, 2020, 04:56:58 pm
content: I don't see the problem with 8 and 16 bit periphery registers. pins on SAMC is a good example. You have registers to setup a pin, but you have 2 pins per register so if you are trying to do anything vaguely automated that requires address arithmetic it just becomes harder although i suppose this is where the 8 and 16 bit access comes handy along with the byte addressing rather than word addressing as it makes writing code easier.

author: ataradov
author_rank: Super Contributor
timestamp: January 05, 2020, 05:37:37 pm
content: Non 32-bit peripheral registers are plain annoying. Partially because it is not really predictable if certain register can be accessed by bytes or not. Not all of them can.The problem of better pin manipulation is solved be actually designing better peripherals. For GPIOs, foe example, it would be bets to have two "views". One is for simultaneous manipulation of all the bits, and another for manipulating individual bits. In the first case you would have one 32-bit register representing pin direction, anther register representing state, etc. This can have optional mask applied as well. In the later case you would have an array of 32 registers representing all settings for each pin.You can mix and match. You can initialize all pins at once, for example, and later use individual pins because that's what you want to do most of the time.This will make writing code actually fun and easy. An all we have to do is make chip designers actually take input from programmers.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 05, 2020, 06:13:42 pm
content: Bit access on some architectures is resolved with the use of masking registers. For instance, for some register (such as GPIO latches), there can be two associated registers, with each bit set either setting or clearing the associated bit in the target register. Some architectures even provide a third, "toggle" register to toggle bits. The benefit compared to single bit-addressing instructions is that you can modify one or several bits in just one instruction. You can usually still directly write to the latch registers as well, so that gives maximum flexibility IMO.

author: ataradov
author_rank: Super Contributor
timestamp: January 05, 2020, 06:27:38 pm
content: Yes, absolutely, SAM C has all of that. The issue comes with more supplementary controls. Like drive strength, pull-up, alternative function, etc. All of that I would rather see located in a single register per pin. And usually all of that is spread all over the place. You can still have corresponding register for setting/clearing individual bits in this registers, of course.