1 /* 2 * FreeRTOS Kernel V11.1.0 3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT AND BSD-3-Clause 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * https://www.FreeRTOS.org 25 * https://github.com/FreeRTOS 26 * 27 */ 28 29 /*This file has been prepared for Doxygen automatic documentation generation.*/ 30 31 /*! \file ********************************************************************* 32 * 33 * \brief FreeRTOS port header for AVR32 UC3. 34 * 35 * - Compiler: IAR EWAVR32 36 * - Supported devices: All AVR32 devices can be used. 37 * - AppNote: 38 * 39 * \author Atmel Corporation (Now Microchip): 40 * https://www.microchip.com 41 * Support and FAQ: https://www.microchip.com/support 42 * 43 *****************************************************************************/ 44 45 /* 46 * Copyright (c) 2007, Atmel Corporation All rights reserved. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions are met: 50 * 51 * 1. Redistributions of source code must retain the above copyright notice, 52 * this list of conditions and the following disclaimer. 53 * 54 * 2. Redistributions in binary form must reproduce the above copyright notice, 55 * this list of conditions and the following disclaimer in the documentation 56 * and/or other materials provided with the distribution. 57 * 58 * 3. The name of ATMEL may not be used to endorse or promote products derived 59 * from this software without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED 62 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 63 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND 64 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, 65 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 66 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 67 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 68 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 69 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 70 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 71 */ 72 73 74 75 #ifndef PORTMACRO_H 76 #define PORTMACRO_H 77 78 /*----------------------------------------------------------- 79 * Port specific definitions. 80 * 81 * The settings in this file configure FreeRTOS correctly for the 82 * given hardware and compiler. 83 * 84 * These settings should not be altered. 85 *----------------------------------------------------------- 86 */ 87 #include <avr32/io.h> 88 #include "intc.h" 89 #include "compiler.h" 90 91 /* *INDENT-OFF* */ 92 #ifdef __cplusplus 93 extern "C" { 94 #endif 95 /* *INDENT-ON* */ 96 97 98 /* Type definitions. */ 99 #define portCHAR char 100 #define portFLOAT float 101 #define portDOUBLE double 102 #define portLONG long 103 #define portSHORT short 104 #define portSTACK_TYPE uint32_t 105 #define portBASE_TYPE long 106 107 typedef portSTACK_TYPE StackType_t; 108 typedef long BaseType_t; 109 typedef unsigned long UBaseType_t; 110 111 112 #define TASK_DELAY_MS( x ) ( ( x ) / portTICK_PERIOD_MS ) 113 #define TASK_DELAY_S( x ) ( ( x ) * 1000 / portTICK_PERIOD_MS ) 114 #define TASK_DELAY_MIN( x ) ( ( x ) * 60 * 1000 / portTICK_PERIOD_MS ) 115 116 #define configTICK_TC_IRQ ATPASTE2( AVR32_TC_IRQ, configTICK_TC_CHANNEL ) 117 118 #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) 119 typedef uint16_t TickType_t; 120 #define portMAX_DELAY ( TickType_t ) 0xffff 121 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) 122 typedef uint32_t TickType_t; 123 #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFFUL ) 124 #else 125 #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. 126 #endif 127 /*-----------------------------------------------------------*/ 128 129 /* Architecture specifics. */ 130 #define portSTACK_GROWTH ( -1 ) 131 #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) 132 #define portBYTE_ALIGNMENT 4 133 #define portNOP() { __asm__ __volatile__ ( "nop" ); } 134 /*-----------------------------------------------------------*/ 135 136 137 /*-----------------------------------------------------------*/ 138 139 /* INTC-specific. */ 140 #define DISABLE_ALL_EXCEPTIONS() Disable_global_exception() 141 #define ENABLE_ALL_EXCEPTIONS() Enable_global_exception() 142 143 #define DISABLE_ALL_INTERRUPTS() Disable_global_interrupt() 144 #define ENABLE_ALL_INTERRUPTS() Enable_global_interrupt() 145 146 #define DISABLE_INT_LEVEL( int_lev ) Disable_interrupt_level( int_lev ) 147 #define ENABLE_INT_LEVEL( int_lev ) Enable_interrupt_level( int_lev ) 148 149 150 /* 151 * Debug trace. 152 * Activated if and only if configDBG is nonzero. 153 * Prints a formatted string to stdout. 154 * The current source file name and line number are output with a colon before 155 * the formatted string. 156 * A carriage return and a linefeed are appended to the output. 157 * stdout is redirected to the USART configured by configDBG_USART. 158 * The parameters are the same as for the standard printf function. 159 * There is no return value. 160 * SHALL NOT BE CALLED FROM WITHIN AN INTERRUPT as fputs and printf use malloc, 161 * which is interrupt-unsafe with the current __malloc_lock and __malloc_unlock. 162 */ 163 #if configDBG 164 #define portDBG_TRACE( ... ) \ 165 { \ 166 fputs( __FILE__ ":" ASTRINGZ( __LINE__ ) ": ", stdout ); \ 167 printf( __VA_ARGS__ ); \ 168 fputs( "\r\n", stdout ); \ 169 } 170 #else 171 #define portDBG_TRACE( ... ) 172 #endif 173 174 175 /* Critical section management. */ 176 #define portDISABLE_INTERRUPTS() DISABLE_ALL_INTERRUPTS() 177 #define portENABLE_INTERRUPTS() ENABLE_ALL_INTERRUPTS() 178 179 180 extern void vPortEnterCritical( void ); 181 extern void vPortExitCritical( void ); 182 183 #define portENTER_CRITICAL() vPortEnterCritical(); 184 #define portEXIT_CRITICAL() vPortExitCritical(); 185 186 187 /* Added as there is no such function in FreeRTOS. */ 188 extern void * pvPortRealloc( void * pv, 189 size_t xSize ); 190 /*-----------------------------------------------------------*/ 191 192 193 /*=============================================================================================*/ 194 195 /* 196 * Restore Context for cases other than INTi. 197 */ 198 #define portRESTORE_CONTEXT() \ 199 { \ 200 extern volatile uint32_t ulCriticalNesting; \ 201 extern volatile void * volatile pxCurrentTCB; \ 202 \ 203 __asm__ __volatile__ ( \ 204 /* Set SP to point to new stack */ \ 205 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 206 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 207 "ld.w r0, r8[0] \n\t" \ 208 "ld.w sp, r0[0] \n\t" \ 209 \ 210 /* Restore ulCriticalNesting variable */ \ 211 "ld.w r0, sp++ \n\t" \ 212 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 213 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 214 "st.w r8[0], r0 \n\t" \ 215 \ 216 /* Restore R0..R7 */ \ 217 "ldm sp++, r0-r7 \n\t" \ 218 /* R0-R7 should not be used below this line */ \ 219 /* Skip PC and SR (will do it at the end) */ \ 220 "sub sp, -2*4 \n\t" \ 221 /* Restore R8..R12 and LR */ \ 222 "ldm sp++, r8-r12, lr \n\t" \ 223 /* Restore SR */ \ 224 "ld.w r0, sp[-8*4] \n\t" /* R0 is modified, is restored later. */ \ 225 "mtsr "ASTRINGZ ( AVR32_SR ) ", r0 \n\t" \ 226 /* Restore r0 */ \ 227 "ld.w r0, sp[-9*4] \n\t" \ 228 /* Restore PC */ \ 229 "ld.w pc, sp[-7*4]" /* Get PC from stack - PC is the 7th register saved */ \ 230 ); \ 231 \ 232 /* Force import of global symbols from assembly */ \ 233 ulCriticalNesting; \ 234 pxCurrentTCB; \ 235 } 236 237 238 /* 239 * portSAVE_CONTEXT_INT() and portRESTORE_CONTEXT_INT(): for INT0..3 exceptions. 240 * portSAVE_CONTEXT_SCALL() and portRESTORE_CONTEXT_SCALL(): for the scall exception. 241 * 242 * Had to make different versions because registers saved on the system stack 243 * are not the same between INT0..3 exceptions and the scall exception. 244 */ 245 246 /* Task context stack layout: */ 247 /* R8 (*) */ 248 /* R9 (*) */ 249 /* R10 (*) */ 250 /* R11 (*) */ 251 /* R12 (*) */ 252 /* R14/LR (*) */ 253 /* R15/PC (*) */ 254 /* SR (*) */ 255 /* R0 */ 256 /* R1 */ 257 /* R2 */ 258 /* R3 */ 259 /* R4 */ 260 /* R5 */ 261 /* R6 */ 262 /* R7 */ 263 /* ulCriticalNesting */ 264 /* (*) automatically done for INT0..INT3, but not for SCALL */ 265 266 /* 267 * The ISR used for the scheduler tick depends on whether the cooperative or 268 * the preemptive scheduler is being used. 269 */ 270 #if configUSE_PREEMPTION == 0 271 272 /* 273 * portSAVE_CONTEXT_OS_INT() for OS Tick exception. 274 */ 275 #define portSAVE_CONTEXT_OS_INT() \ 276 { \ 277 /* Save R0..R7 */ \ 278 __asm__ __volatile__ ( "stm --sp, r0-r7" ); \ 279 \ 280 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \ 281 /* there is also no context save. */ \ 282 } 283 284 /* 285 * portRESTORE_CONTEXT_OS_INT() for Tick exception. 286 */ 287 #define portRESTORE_CONTEXT_OS_INT() \ 288 { \ 289 __asm__ __volatile__ ( \ 290 /* Restore R0..R7 */ \ 291 "ldm sp++, r0-r7 \n\t" \ 292 \ 293 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \ 294 /* there is also no context restore. */ \ 295 "rete" \ 296 ); \ 297 } 298 299 #else /* if configUSE_PREEMPTION == 0 */ 300 301 /* 302 * portSAVE_CONTEXT_OS_INT() for OS Tick exception. 303 */ 304 #define portSAVE_CONTEXT_OS_INT() \ 305 { \ 306 extern volatile uint32_t ulCriticalNesting; \ 307 extern volatile void * volatile pxCurrentTCB; \ 308 \ 309 /* When we come here */ \ 310 /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \ 311 \ 312 __asm__ __volatile__ ( \ 313 /* Save R0..R7 */ \ 314 "stm --sp, r0-r7 \n\t" \ 315 \ 316 /* Save ulCriticalNesting variable - R0 is overwritten */ \ 317 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 318 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 319 "ld.w r0, r8[0] \n\t" \ 320 "st.w --sp, r0 \n\t" \ 321 \ 322 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \ 323 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \ 324 /* level and allow other lower interrupt level to occur). */ \ 325 /* In this case we don't want to do a task switch because we don't know what the stack */ \ 326 /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \ 327 /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \ 328 /* will just be restoring the interrupt handler, no way!!! */ \ 329 /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \ 330 "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */ \ 331 "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */ \ 332 "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */ \ 333 "brhi LABEL_INT_SKIP_SAVE_CONTEXT_"ASTRINGZ ( __LINE__ ) " \n\t" \ 334 \ 335 /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \ 336 /* NOTE: we don't enter a critical section here because all interrupt handlers */ \ 337 /* MUST perform a SAVE_CONTEXT/RESTORE_CONTEXT in the same way as */ \ 338 /* portSAVE_CONTEXT_OS_INT/port_RESTORE_CONTEXT_OS_INT if they call OS functions. */ \ 339 /* => all interrupt handlers must use portENTER_SWITCHING_ISR/portEXIT_SWITCHING_ISR. */ \ 340 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 341 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 342 "ld.w r0, r8[0] \n\t" \ 343 "st.w r0[0], sp \n" \ 344 \ 345 "LABEL_INT_SKIP_SAVE_CONTEXT_"ASTRINGZ ( __LINE__ ) ":" \ 346 ); \ 347 } 348 349 /* 350 * portRESTORE_CONTEXT_OS_INT() for Tick exception. 351 */ 352 #define portRESTORE_CONTEXT_OS_INT() \ 353 { \ 354 extern volatile uint32_t ulCriticalNesting; \ 355 extern volatile void * volatile pxCurrentTCB; \ 356 \ 357 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \ 358 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \ 359 /* level and allow other lower interrupt level to occur). */ \ 360 /* In this case we don't want to do a task switch because we don't know what the stack */ \ 361 /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \ 362 /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \ 363 /* will just be restoring the interrupt handler, no way!!! */ \ 364 __asm__ __volatile__ ( \ 365 "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */ \ 366 "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */ \ 367 "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */ \ 368 "brhi LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ ( __LINE__ ) \ 369 ); \ 370 \ 371 /* Else */ \ 372 /* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */ \ 373 /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */ \ 374 portENTER_CRITICAL(); \ 375 vTaskSwitchContext(); \ 376 portEXIT_CRITICAL(); \ 377 \ 378 /* Restore all registers */ \ 379 \ 380 __asm__ __volatile__ ( \ 381 /* Set SP to point to new stack */ \ 382 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 383 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 384 "ld.w r0, r8[0] \n\t" \ 385 "ld.w sp, r0[0] \n" \ 386 \ 387 "LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ ( __LINE__ ) ": \n\t" \ 388 \ 389 /* Restore ulCriticalNesting variable */ \ 390 "ld.w r0, sp++ \n\t" \ 391 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 392 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 393 "st.w r8[0], r0 \n\t" \ 394 \ 395 /* Restore R0..R7 */ \ 396 "ldm sp++, r0-r7 \n\t" \ 397 \ 398 /* Now, the stack should be R8..R12, LR, PC and SR */ \ 399 "rete" \ 400 ); \ 401 \ 402 /* Force import of global symbols from assembly */ \ 403 ulCriticalNesting; \ 404 pxCurrentTCB; \ 405 } 406 407 #endif /* if configUSE_PREEMPTION == 0 */ 408 409 410 /* 411 * portSAVE_CONTEXT_SCALL() for SupervisorCALL exception. 412 * 413 * NOTE: taskYIELD()(== SCALL) MUST NOT be called in a mode > supervisor mode. 414 * 415 */ 416 #define portSAVE_CONTEXT_SCALL() \ 417 { \ 418 extern volatile uint32_t ulCriticalNesting; \ 419 extern volatile void * volatile pxCurrentTCB; \ 420 \ 421 /* Warning: the stack layout after SCALL doesn't match the one after an interrupt. */ \ 422 /* If SR[M2:M0] == 001 */ \ 423 /* PC and SR are on the stack. */ \ 424 /* Else (other modes) */ \ 425 /* Nothing on the stack. */ \ 426 \ 427 /* WARNING NOTE: the else case cannot happen as it is strictly forbidden to call */ \ 428 /* vTaskDelay() and vTaskDelayUntil() OS functions (that result in a taskYield()) */ \ 429 /* in an interrupt|exception handler. */ \ 430 \ 431 __asm__ __volatile__ ( \ 432 /* in order to save R0-R7 */ \ 433 "sub sp, 6*4 \n\t" \ 434 /* Save R0..R7 */ \ 435 "stm --sp, r0-r7 \n\t" \ 436 \ 437 /* in order to save R8-R12 and LR */ \ 438 /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \ 439 "sub r7, sp,-16*4 \n\t" \ 440 /* Copy PC and SR in other places in the stack. */ \ 441 "ld.w r0, r7[-2*4] \n\t" /* Read SR */ \ 442 "st.w r7[-8*4], r0 \n\t" /* Copy SR */ \ 443 "ld.w r0, r7[-1*4] \n\t" /* Read PC */ \ 444 "st.w r7[-7*4], r0 \n\t" /* Copy PC */ \ 445 \ 446 /* Save R8..R12 and LR on the stack. */ \ 447 "stm --r7, r8-r12, lr \n\t" \ 448 \ 449 /* Arriving here we have the following stack organizations: */ \ 450 /* R8..R12, LR, PC, SR, R0..R7. */ \ 451 \ 452 /* Now we can finalize the save. */ \ 453 \ 454 /* Save ulCriticalNesting variable - R0 is overwritten */ \ 455 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 456 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 457 "ld.w r0, r8[0] \n\t" \ 458 "st.w --sp, r0" \ 459 ); \ 460 \ 461 /* Disable the its which may cause a context switch (i.e. cause a change of */ \ 462 /* pxCurrentTCB). */ \ 463 /* Basically, all accesses to the pxCurrentTCB structure should be put in a */ \ 464 /* critical section because it is a global structure. */ \ 465 portENTER_CRITICAL(); \ 466 \ 467 /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \ 468 __asm__ __volatile__ ( \ 469 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 470 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 471 "ld.w r0, r8[0] \n\t" \ 472 "st.w r0[0], sp" \ 473 ); \ 474 } 475 476 /* 477 * portRESTORE_CONTEXT() for SupervisorCALL exception. 478 */ 479 #define portRESTORE_CONTEXT_SCALL() \ 480 { \ 481 extern volatile uint32_t ulCriticalNesting; \ 482 extern volatile void * volatile pxCurrentTCB; \ 483 \ 484 /* Restore all registers */ \ 485 \ 486 /* Set SP to point to new stack */ \ 487 __asm__ __volatile__ ( \ 488 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 489 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 490 "ld.w r0, r8[0] \n\t" \ 491 "ld.w sp, r0[0]" \ 492 ); \ 493 \ 494 /* Leave pxCurrentTCB variable access critical section */ \ 495 portEXIT_CRITICAL(); \ 496 \ 497 __asm__ __volatile__ ( \ 498 /* Restore ulCriticalNesting variable */ \ 499 "ld.w r0, sp++ \n\t" \ 500 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 501 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 502 "st.w r8[0], r0 \n\t" \ 503 \ 504 /* skip PC and SR */ \ 505 /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \ 506 "sub r7, sp, -10*4 \n\t" \ 507 /* Restore r8-r12 and LR */ \ 508 "ldm r7++, r8-r12, lr \n\t" \ 509 \ 510 /* RETS will take care of the extra PC and SR restore. */ \ 511 /* So, we have to prepare the stack for this. */ \ 512 "ld.w r0, r7[-8*4] \n\t" /* Read SR */ \ 513 "st.w r7[-2*4], r0 \n\t" /* Copy SR */ \ 514 "ld.w r0, r7[-7*4] \n\t" /* Read PC */ \ 515 "st.w r7[-1*4], r0 \n\t" /* Copy PC */ \ 516 \ 517 /* Restore R0..R7 */ \ 518 "ldm sp++, r0-r7 \n\t" \ 519 \ 520 "sub sp, -6*4 \n\t" \ 521 \ 522 "rets" \ 523 ); \ 524 \ 525 /* Force import of global symbols from assembly */ \ 526 ulCriticalNesting; \ 527 pxCurrentTCB; \ 528 } 529 530 531 /* 532 * The ISR used depends on whether the cooperative or 533 * the preemptive scheduler is being used. 534 */ 535 #if configUSE_PREEMPTION == 0 536 537 /* 538 * ISR entry and exit macros. These are only required if a task switch 539 * is required from the ISR. 540 */ 541 #define portENTER_SWITCHING_ISR() \ 542 { \ 543 /* Save R0..R7 */ \ 544 __asm__ __volatile__ ( "stm --sp, r0-r7" ); \ 545 \ 546 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \ 547 /* there is also no context save. */ \ 548 } 549 550 /* 551 * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1 552 */ 553 #define portEXIT_SWITCHING_ISR() \ 554 { \ 555 __asm__ __volatile__ ( \ 556 /* Restore R0..R7 */ \ 557 "ldm sp++, r0-r7 \n\t" \ 558 \ 559 /* With the cooperative scheduler, as there is no context switch by interrupt, */ \ 560 /* there is also no context restore. */ \ 561 "rete" \ 562 ); \ 563 } 564 565 #else /* if configUSE_PREEMPTION == 0 */ 566 567 /* 568 * ISR entry and exit macros. These are only required if a task switch 569 * is required from the ISR. 570 */ 571 #define portENTER_SWITCHING_ISR() \ 572 { \ 573 extern volatile uint32_t ulCriticalNesting; \ 574 extern volatile void * volatile pxCurrentTCB; \ 575 \ 576 /* When we come here */ \ 577 /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \ 578 \ 579 __asm__ __volatile__ ( \ 580 /* Save R0..R7 */ \ 581 "stm --sp, r0-r7 \n\t" \ 582 \ 583 /* Save ulCriticalNesting variable - R0 is overwritten */ \ 584 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 585 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 586 "ld.w r0, r8[0] \n\t" \ 587 "st.w --sp, r0 \n\t" \ 588 \ 589 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \ 590 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \ 591 /* level and allow other lower interrupt level to occur). */ \ 592 /* In this case we don't want to do a task switch because we don't know what the stack */ \ 593 /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \ 594 /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \ 595 /* will just be restoring the interrupt handler, no way!!! */ \ 596 /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \ 597 "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */ \ 598 "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */ \ 599 "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */ \ 600 "brhi LABEL_ISR_SKIP_SAVE_CONTEXT_"ASTRINGZ ( __LINE__ ) " \n\t" \ 601 \ 602 /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \ 603 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 604 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 605 "ld.w r0, r8[0] \n\t" \ 606 "st.w r0[0], sp \n" \ 607 \ 608 "LABEL_ISR_SKIP_SAVE_CONTEXT_"ASTRINGZ ( __LINE__ ) ":" \ 609 ); \ 610 } 611 612 613 /* 614 * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1 615 */ 616 #define portEXIT_SWITCHING_ISR() \ 617 { \ 618 extern volatile uint32_t ulCriticalNesting; \ 619 extern volatile void * volatile pxCurrentTCB; \ 620 \ 621 __asm__ __volatile__ ( \ 622 /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \ 623 /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \ 624 /* level and allow other lower interrupt level to occur). */ \ 625 /* In this case it's of no use to switch context and restore a new SP because we purposely */ \ 626 /* did not previously save SP in its TCB. */ \ 627 "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */ \ 628 "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */ \ 629 "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */ \ 630 "brhi LABEL_ISR_SKIP_RESTORE_CONTEXT_"ASTRINGZ ( __LINE__ ) " \n\t" \ 631 \ 632 /* If a switch is required then we just need to call */ \ 633 /* vTaskSwitchContext() as the context has already been */ \ 634 /* saved. */ \ 635 "cp.w r12, 1 \n\t" /* Check if Switch context is required. */ \ 636 "brne LABEL_ISR_RESTORE_CONTEXT_"ASTRINGZ ( __LINE__ ) ":C" \ 637 ); \ 638 \ 639 /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */ \ 640 portENTER_CRITICAL(); \ 641 vTaskSwitchContext(); \ 642 portEXIT_CRITICAL(); \ 643 \ 644 __asm__ __volatile__ ( \ 645 "LABEL_ISR_RESTORE_CONTEXT_"ASTRINGZ ( __LINE__ ) ": \n\t" \ 646 /* Restore the context of which ever task is now the highest */ \ 647 /* priority that is ready to run. */ \ 648 \ 649 /* Restore all registers */ \ 650 \ 651 /* Set SP to point to new stack */ \ 652 "mov r8, LWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 653 "orh r8, HWRD("ASTRINGZ ( pxCurrentTCB ) ") \n\t" \ 654 "ld.w r0, r8[0] \n\t" \ 655 "ld.w sp, r0[0] \n" \ 656 \ 657 "LABEL_ISR_SKIP_RESTORE_CONTEXT_"ASTRINGZ ( __LINE__ ) ": \n\t" \ 658 \ 659 /* Restore ulCriticalNesting variable */ \ 660 "ld.w r0, sp++ \n\t" \ 661 "mov r8, LWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 662 "orh r8, HWRD("ASTRINGZ ( ulCriticalNesting ) ") \n\t" \ 663 "st.w r8[0], r0 \n\t" \ 664 \ 665 /* Restore R0..R7 */ \ 666 "ldm sp++, r0-r7 \n\t" \ 667 \ 668 /* Now, the stack should be R8..R12, LR, PC and SR */ \ 669 "rete" \ 670 ); \ 671 \ 672 /* Force import of global symbols from assembly */ \ 673 ulCriticalNesting; \ 674 pxCurrentTCB; \ 675 } 676 677 #endif /* if configUSE_PREEMPTION == 0 */ 678 679 680 #define portYIELD() { __asm__ __volatile__ ( "scall" ); } 681 682 /* Task function macros as described on the FreeRTOS.org WEB site. */ 683 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) 684 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) 685 686 /* *INDENT-OFF* */ 687 #ifdef __cplusplus 688 } 689 #endif 690 /* *INDENT-ON* */ 691 692 #endif /* PORTMACRO_H */ 693