SPRU514Z July 2001 – October 2023 SM320F28335-EP
The C2000 architecture has 16-bit words. Some peripherals, however, are 8-bit byte addressable. The byte peripherals bridge translates addresses between the CPU and byte peripherals by treating an address as a byte address. Therefore, only some C2000 addresses map correctly to the byte peripherals. Even and odd addresses to 16-bit data both map to the same data element on the byte peripheral.
The same is true for addresses to 32-bit data. Addresses for 16-bit accesses must be 32-bit aligned and those for 32-bit accesses must be 64-bit aligned.
C2000 driver libraries and bitfield header files are provided to access peripherals. To support correct accesses to byte peripheral data, the compiler provides the __byte_peripheral_32 intrinsic and the byte_peripheral type attribute.
The C2000 driver library accesses byte peripheral data at the correct starting address. However, on the C2000, operations on 32-bit data are often broken up into two operations on 16-bit data because these are more efficient on the architecture. Accesses to 32-bit byte peripheral data cannot be broken up regularly into two 16-bit accesses because the starting offset for the second 16-bits will be incorrect. The __byte_peripheral_32 intrinsic can be used to access a 32-bit byte peripheral data address, preventing these accesses from being broken up. The intrinsic returns a reference to an unsigned long and can be used both to read and write data. See Section 7.6 for information about this intrinsic.
The byte_peripheral type attribute can be applied as follows to typedefs of unsigned ints and unsigned longs for bitfield support.
typedef unsigned int bp_16 __attribute__((byte_peripheral)) ;
typedef unsigned long bp_32 __attribute__((byte_peripheral));
The typedef names are not significant. The attributes automatically apply the volatile keyword and handle alignment. All struct members in byte peripheral structs, whether they are bitfields or not, must have these attributes applied via typedefs to ensure proper alignment of the struct accesses. Note that struct layout is different due to differences in alignment, so the bitfields cannot always be accessed via the same container types as in regular structs.
For example, the bit positions for byte peripheral bitfield types are compared in the following examples to the positions of regular bitfields. Because 16-bit accesses must be 32-bit aligned, it is not possible to access bits at offsets 16-31 with a 16-bit container. To access these bits, a 32-bit container must be used. In example 1, you could create the same layout as in the regular case by changing the field types to bp_32 for field4 through field6. In example 2, you would change the field types to bp_32 for field2 through field4.
struct example1 { // regular bits position //byte peripherals
bp_16 field1:9; // 0-8 // 0-8
bp_16 field2:6; // 9-14 // 9-14
bp_32 field3:4; // 15-18 // 15-18
bp_16 field4:1; // 19 // 32
bp_16 field5:5; // 20-24 // 33-37
bp_16 field6:7; // 25-31 // 38-44
};
struct example2{ // regular bits position //byte peripherals
bp_32 field1:29; // 0-28 // 0-28
bp_16 field2:1; // 29 // 32
bp_16 field3:1; // 30 // 33
bp_16 field4:1; // 31 // 34
};
Because the alignment will create padding in any objects that are declared, it is recommended that you cast byte peripheral addresses as byte peripheral struct types instead of declaring objects of those struct types.
You cannot create arrays using the byte peripheral type attribute. This is because the C language guarantees that the size of an array is the same as the size of each element times the number of elements. This would not be the case in an array of byte peripherals, because there would need to be padding in the array.