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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
|
/**
* #######################################################################################
* GAYE Abdoulaye Walsimou, <walsimou@walsimou.com>
* Copyright (C) 2009 GAYE Abdoulaye walsimou. All rights reserved.
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License
* (Version 2 or later) published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
* #######################################################################################
*
* \file portmacro.h
* \brief portmacro.h for PIC18 SDCC port as required for FreeRTOS
* \brief It is based on existing PIC18 port.
* \author GAYE Abdoulaye Walsimou, <walsimou@walsimou.com>
* \date february 2009
* #######################################################################################
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#include <pic18fregs.h>
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portINT int
#define portSHORT short
#define portSTACK_TYPE __data unsigned char
#define portBASE_TYPE char
/* Some memory areas get saved as part of the task context. These memory
area's get used by the compiler for temporary storage, especially when
performing mathematical operations, or when using 32bit data types. This
constant defines the size of memory area which must be saved. */
#define portCOMPILER_MANAGED_MEMORY_SIZE (20)
#if(configUSE_16_BIT_TICKS==1)
typedef unsigned portSHORT portTickType;
#define portMAX_DELAY (portTickType)0xffff
#else
typedef unsigned portLONG portTickType;
#define portMAX_DELAY (portTickType)0xffffffff
#endif
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portBYTE_ALIGNMENT 1
#define portGLOBAL_INT_ENABLE_BIT 0x80
#define portSTACK_GROWTH -1
#define portTICK_RATE_MS (1000/configTICK_RATE_HZ)
/*-----------------------------------------------------------*/
/*
* Critical section management.
*/
#define portDISABLE_INTERRUPTS() \
do \
{ \
INTCONbits.GIE = 0; \
}while(INTCONbits.GIE)
#define portENABLE_INTERRUPTS() INTCONbits.GIE = 1
/* Push the INTCON register onto the stack, then disable interrupts. */
#define portENTER_CRITICAL() POSTDEC1 = INTCON; portDISABLE_INTERRUPTS()
/* Retrieve the INTCON register from the stack, and enable interrupts
if they were saved as being enabled. Don't modify any other bits
within the INTCON register as these may have lagitimately have been
modified within the critical region. */
#define portEXIT_CRITICAL() \
_asm \
MOVF PREINC1, 1, 0; \
_endasm; \
if(INDF1&portGLOBAL_INT_ENABLE_BIT) \
{ \
portENABLE_INTERRUPTS(); \
}
/*-----------------------------------------------------------*/
/* Task utilities. */
extern void vPortYield(void) __naked;
#define portYIELD() vPortYield()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
/*-----------------------------------------------------------*/
/* Required by the kernel aware debugger. */
#ifdef __DEBUG
#define portREMOVE_STATIC_QUALIFIER
#endif
#define portNOP() Nop()
/*
* portSAVE_CONTEXT(ucForcedInterruptFlags):
* Macro that pushes all the registers that make up the context of a task onto
* the stack, then saves the new top of stack into the TCB.
*
* If this is called from an ISR then the interrupt enable bits must have been
* set for the ISR to ever get called. Therefore we want to save the INTCON
* register with the enable bits forced to be set - and ucForcedInterruptFlags
* must contain these bit settings. This means the interrupts will again be
* enabled when the interrupted task is switched back in.
*
* If this is called from a manual context switch (i.e. from a call to yield),
* then we want to save the INTCON so it is restored with its current state,
* and ucForcedInterruptFlags must be 0. This allows a yield from within
* a critical section.
*
* The compiler uses some locations at the bottom of the memory for temporary
* storage during math and other computations. This is especially true if
* 32bit data types are utilised (as they are by the scheduler). The .registers
* section have to be stored in there entirety as part of a task context.
* This macro stores from data address 0x00 to portCOMPILER_MANAGED_MEMORY_SIZE.
* This is sufficient for the demo applications but you should check the map file
* for your project to ensure this is sufficient for your needs.
* It is not clear whether this size is fixed for all compilations or has the
* potential to be program specific.
*/
#pragma preproc_asm -
#define portSAVE_CONTEXT_GLOBAL_REGISTERS() _asm
;Save the status and WREG registers first, as these will get modified
;by the operations below.
MOVFF WREG,POSTDEC1
MOVFF STATUS,POSTDEC1
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portSAVE_CONTEXT_HW_REGISTERS() _asm
;Store the necessary hardware registers to the stack.
MOVFF BSR,POSTDEC1
MOVFF PRODL,POSTDEC1
MOVFF PRODH,POSTDEC1
MOVFF FSR0L,POSTDEC1
MOVFF FSR0H,POSTDEC1
MOVFF PCLATH,POSTDEC1
MOVFF PCLATU,POSTDEC1
MOVFF FSR2H,POSTDEC1
MOVFF FSR2L,POSTDEC1
MOVFF TABLAT,POSTDEC1
MOVFF TBLPTRL,POSTDEC1
MOVFF TBLPTRH,POSTDEC1
MOVFF TBLPTRU,POSTDEC1
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portSAVE_CONTEXT_DOT_REGISTERS_START() _asm
;Start to store .registers areas as described above.
CLRF FSR0L,ACCESS
CLRF FSR0H,ACCESS
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portSAVE_CONTEXT_DOT_REGISTERS_END() _asm
MOVFF INDF0,POSTDEC1
;Store the end address of.registers section.
MOVFF FSR0L,POSTDEC1
MOVFF FSR0H,POSTDEC1
;Store the hardware stack pointer in a temp register (FSR0L) before we
;modify it.
MOVFF STKPTR,FSR0L
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portSAVE_CONTEXT_HWSTACK() _asm
MOVFF TOSL,POSTDEC1
MOVFF TOSH,POSTDEC1
MOVFF TOSU,POSTDEC1
POP
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portSAVE_CONTEXT_END() _asm
;Store the number of addresses on the hardware stack (from the
;temporary register FSR0L).
MOVFF FSR0L,POSTDEC1
;Save the new top of the software stack in the TCB.
MOVFF _pxCurrentTCB,FSR0L
MOVFF _pxCurrentTCB+1,FSR0H
MOVFF FSR1L,POSTINC0
MOVFF FSR1H,POSTINC0
_endasm
#pragma preproc_asm +
#define portSAVE_CONTEXT(ucForcedInterruptFlags) \
{ \
portSAVE_CONTEXT_GLOBAL_REGISTERS(); \
_asm \
MOVFF INTCON,WREG \
_endasm; \
_asm \
IORLW ucForcedInterruptFlags \
_endasm; \
_asm \
MOVFF WREG,POSTDEC1 \
_endasm; \
portDISABLE_INTERRUPTS(); \
portSAVE_CONTEXT_HW_REGISTERS(); \
portSAVE_CONTEXT_DOT_REGISTERS_START(); \
_asm \
MOVLW (portCOMPILER_MANAGED_MEMORY_SIZE-1) \
_endasm; \
_asm \
MOVFF POSTINC0,POSTDEC1 \
_endasm; \
_asm \
DECFSZ WREG,ACCESS \
_endasm; \
_asm \
BRA ($ - 5) \
_endasm; \
portSAVE_CONTEXT_DOT_REGISTERS_END(); \
while(STKPTR>(unsigned portCHAR)0) \
{ \
portSAVE_CONTEXT_HWSTACK(); \
} \
portSAVE_CONTEXT_END(); \
}
/*-----------------------------------------------------------*/
/*
* portRESTORE_CONTEXT():
* This is the reverse of portSAVE_CONTEXT. See portSAVE_CONTEXT for more
* details.
*/
#pragma preproc_asm -
#define portRESTORE_CONTEXT_GET_PXCURRENTTCB() _asm
;Set FSR0 to point to pxCurrentTCB.
MOVFF _pxCurrentTCB,FSR0L
MOVFF _pxCurrentTCB+1,FSR0H
;De-reference FSR0 to set the address it holds into FSR1.
;(i.e. pxCurrentTCB->pxTopOfStack)
MOVFF POSTINC0,FSR1L
MOVFF POSTINC0,FSR1H
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_GET_STACKDEPTH() _asm
;How many return addresses are there on the hardware stack?
MOVFF PREINC1, FSR0L
;(Above FSR0L is used as temp register.)
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_FILL_HWSTACK() _asm
PUSH
MOVF PREINC1,0,ACCESS
MOVWF TOSU,ACCESS
MOVF PREINC1,0,ACCESS
MOVWF TOSH,ACCESS
MOVF PREINC1,0,ACCESS
MOVWF TOSL,ACCESS
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_DOT_REGISTERS_START() _asm
;Start to restore the .registers section.
MOVFF PREINC1,FSR0H
MOVFF PREINC1,FSR0L
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_DOT_REGISTERS_END() _asm
;End to restore the .registers section.
MOVFF PREINC1,INDF0
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_HW_REGISTERS() _asm
;Restore the other registers forming the tasks context.
MOVFF PREINC1,TBLPTRU
MOVFF PREINC1,TBLPTRH
MOVFF PREINC1,TBLPTRL
MOVFF PREINC1,TABLAT
MOVFF PREINC1,FSR2L
MOVFF PREINC1,FSR2H
MOVFF PREINC1,PCLATU
MOVFF PREINC1,PCLATH
MOVFF PREINC1,FSR0H
MOVFF PREINC1,FSR0L
MOVFF PREINC1,PRODH
MOVFF PREINC1,PRODL
MOVFF PREINC1,BSR
;The next byte is the INTCON register. Read this into WREG as some
;manipulation is required.
MOVFF PREINC1, WREG
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_RETFIE() _asm
;From the INTCON register, only the interrupt enable bits form part
;of the tasks context. It is perfectly legitimate for another task to
;have modified any other bits. We therefore only restore the top two bits.
MOVFF PREINC1, STATUS
MOVFF PREINC1, WREG
;Return enabling interrupts.
RETFIE 0
_endasm
#pragma preproc_asm +
#pragma preproc_asm -
#define portRESTORE_CONTEXT_RETURN() _asm
MOVFF PREINC1, STATUS
MOVFF PREINC1, WREG
;Return without effecting interrupts. The context may have
;been saved from a critical region.
RETURN 0
_endasm
#pragma preproc_asm +
#define portRESTORE_CONTEXT() \
{ \
portRESTORE_CONTEXT_GET_PXCURRENTTCB(); \
portRESTORE_CONTEXT_GET_STACKDEPTH(); \
STKPTR = 0; \
while(STKPTR < FSR0L) \
{ \
portRESTORE_CONTEXT_FILL_HWSTACK(); \
} \
portRESTORE_CONTEXT_DOT_REGISTERS_START(); \
_asm \
MOVLW (portCOMPILER_MANAGED_MEMORY_SIZE-1) \
_endasm; \
_asm \
MOVFF PREINC1,POSTDEC0 \
_endasm; \
_asm \
DECFSZ WREG,ACCESS \
_endasm; \
_asm \
BRA ($ - 5) \
_endasm; \
portRESTORE_CONTEXT_DOT_REGISTERS_END(); \
portRESTORE_CONTEXT_HW_REGISTERS(); \
if(WREG & portGLOBAL_INTERRUPT_FLAG) \
{ \
portRESTORE_CONTEXT_RETFIE(); \
} \
else \
{ \
portRESTORE_CONTEXT_RETURN(); \
} \
}
#endif /*PORTMACRO_H*/
|