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