-
Notifications
You must be signed in to change notification settings - Fork 25
/
clpru_and_C_usage.notes
251 lines (145 loc) · 8.72 KB
/
clpru_and_C_usage.notes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
*__attribute__*
In GNU C, you can use function attributes to declare certain things about functions called in your program which
help the compiler optimize calls and check your code more carefully. For example, you can use attributes to declare
that a function never returns (noreturn), returns a value depending only on its arguments (pure), or has
printf-style arguments (format).
You can also use attributes to control memory placement, code generation options or call/return conventions within
the function being annotated. Many of these attributes are target-specific. For example, many targets support attributes
for defining interrupt handler functions, which typically must follow special register usage and return conventions.
Function attributes are introduced by the __attribute__ keyword on a declaration, followed by an attribute specification
inside double parentheses. You can specify multiple attributes in a declaration by separating them by commas within the
double parentheses or by immediately following an attribute declaration with another attribute declaration.
------------------------------
*Data types*
Type Size Representation Minimum Maximum
signed char 8 bits ASCII -128 127
char (unless --
plain_char=unsigned)
unsigned char 8 bits ASCII 0 255
short, signed short 16 bits 2s complement -32,768 32,767
unsigned short 16 bits Binary 0 65,535
int, signed int 32 bits 2s complement -2,147,483,648 2,147,483,647
unsigned int, wchar_t 32 bits Binary 0 4,294,967,295
long, signed long 32 bits 2s complement -2,147,483,648 2,147,483,647
unsigned long 32 bits Binary 0 4,294,967,295
long long, 64 bits 2s complement -9,223,372,036,854,775,808 9,223,372,036,854,775,807
signed long long
unsigned long long 64 bits Binary 0 18,446,744,073,709,551,615
float 32 bits IEEE 32-bit 1.175 494e-38(1) 3.40 282 346e+38
double 64 bits IEEE 64-bit 2.22 507 385e-308(1) 1.79 769 313e+308
long double 64 bits IEEE 64-bit 2.22 507 385e-308(1) 1.79 769 313e+308
data pointers 32 bits Binary 0 0xFFFFFFFF
code pointers 16 bits Binary 0 0xFFFF
-------------------------------
*The near and far Keywords*
The near keyword asserts that a symbol will be in the lower 16 bits of memory. By default all symbols are
near. The PRU local memory is always in the lower 16 bits.
The far keyword asserts that a symbol may be in the upper 16 bits of memory.
The far keyword asserts that a symbol may be in the upper 16 bits of memory.
A cregister symbol can have a far qualifier and be a near cregister access.
__far int peripheral __attribute__((cregister("PERIPH", near)));
This means that relative to the cregister access peripheral, this is a near access. However, if accessed
using an absolute address, this is a far access. This is important because the compiler may choose to not
access a peripheral using a cregister access.
-------------------------------
*cregister*
The cregister attribute provides support for using the constant registers. If the cregister attribute is used,
the peripheral attribute can be used along with it. The syntax is:
int x __attribute__((cregister("MEM", [near|far]), peripheral));
The name "MEM" can be any name, although it will need to correspond to a memory range name in your
linker command file. The near or far parameter tells the compiler whether it can use the immediate
addressing mode (near) or register indirect addressing mode (far). If the data will be completely contained
within the first 256 bytes from the top of the constant register pointer then use near, otherwise use far. The
default is near.
The peripheral attribute can only be used with the cregister attribute and has two effects. First, it puts the
object in a section that will not be loaded onto the device. This prevents initialization of the peripheral at
runtime. Second, it allows the same object to be defined in multiple source files without a linker error. The
intent is that peripherals can be completely described in a header file.
----------------------------------
* packed *
The packed attribute is supported for struct and union types. It is supported if the --relaxed_ansi option
is used.
Members of a packed structure are stored as closely to each other as possible, omitting additional bytes
of padding usually added to preserve word-alignment. For example, assuming a word-size of 4 bytes
ordinarily has 3 bytes of padding between members c1 and i, and another 3 bytes of trailing padding after
member c2, leading to a total size of 12 bytes:
struct unpacked_struct { char c1; int i; char c2;};
However, the members of a packed struct are byte-aligned. Thus the following does not have any bytes of
padding between or after members and totals 6 bytes:
struct __attribute__((__packed__)) packed_struct { char c1; int i; char c2; };
Subsequently, packed structures in an array are packed together without trailing padding between array
elements.
Bit fields of a packed structure are bit-aligned. The byte alignment of adjacent struct members that are
not bit fields does not change. However, there are no bits of padding between adjacent bit fields.
The packed attribute can only be applied to the original definition of a structure or union type. It cannot
be applied with a typedef to a non-packed structure that has already been defined, nor can it be applied to
the declaration of a struct or union object. Therefore, any given structure or union type can only be packed
or non-packed, and all objects of that type will inherit its packed or non-packed attribute.
The packed attribute is not applied recursively to structure types that are contained within a packed structure.
-----------------------------------
* Register Usage *
Register Usage 'Save on Call' 'Save on Entry'
R0.w0 Expression register Yes
R1 Expression register Yes
R2 Stack pointer (SP)
R3.w0 Expression register
R3.w2 Expression register
(usually used as Link Yes
register to store the
return address)
R4 Argument pointer (AP) Yes
R5 Expression register Yes
R6 Expression register Yes
R7 Expression register Yes
R8 Expression register Yes
R9 Expression register Yes
R10 Expression register Yes
R11 Expression register Yes
R12 Expression register Yes
R13 Expression register Yes
R14 Return register Yes
R15 Expression register Yes
R16 Expression register Yes
R17 Expression register Yes
R18 Expression register Yes
R19 Expression register Yes
R20 Expression register Yes
R21 Expression register Yes
R22 Expression register Yes
R23 Expression register Yes
R24 Expression register Yes
R25 Expression register Yes
R26 Expression register Yes
R27 Expression register Yes
R28 Expression register Yes
R29 Expression register Yes
R30 Control register
R31 Control register
------
Argument register Passes arguments during a function call
Return register Holds the return value from a function call
Expression register Holds a value
Argument pointer Used as a base value from which a function's parameters (incoming
arguments) are accessed (AP)
Stack pointer Holds the address of the top of the software stack (SP)
Link register Contains the return address of a function call (LR)
Program counter Contains the current address of code being executed
-----------------------------------------------------------------------------------
void __xin (unsigned int device_id, unsigned int base_register, unsigned int use_remapping, void& object)
void __xout (unsigned int device_id, unsigned int base_register,unsigned int use_remapping, void& object)
void __xchg (unsigned int device_id, unsigned int base_register,unsigned int use_remapping, void& object)
void __sxin (unsigned int device_id, unsigned int base_register, unsigned int use_remapping, void& object)
void __sxout(unsigned int device_id, unsigned int base_register, unsigned int use_remapping, void& object)
void __sxchg(unsigned int device_id, unsigned int base_register, unsigned int use_remapping, void& object)
These intrinsics are used to generate the XFER instructions on the PRU.
The parameters are defined as:
device_id: Literal 0-255 correpsonding to the first parameter of the
assembly instruction.
base_register: Literal 0-32 corresponding to the register that must be used
as the base register for the transfer.
use_remapping: Boolean value (zero is false, non-zero is true) that
specifies whether a register file shift amount is used
to move the registers to the appropriate base register.
An example of this are the bank shift supported for the
scratchpad memory on ICSS.
object: Any object with a size less than 44 bytes.