45 #ifndef _TN_ARCH_PIC32_H
46 #define _TN_ARCH_PIC32_H
53 #include "../../core/tn_cfg_dispatch.h"
89 #ifndef DOXYGEN_SHOULD_SKIP_THIS
91 #define _TN_PIC32_INTSAVE_DATA_INVALID 0xffffffff
94 # define _TN_PIC32_INTSAVE_CHECK() \
96 if (tn_save_status_reg == _TN_PIC32_INTSAVE_DATA_INVALID){ \
97 _TN_FATAL_ERROR(""); \
101 # define _TN_PIC32_INTSAVE_CHECK()
110 #define _TN_FFS(x) (32 - __builtin_clz((x) & (0 - (x))))
119 #define _TN_FATAL_ERROR(error_msg, ...) \
120 {__asm__ volatile(" sdbbp 0"); __asm__ volatile ("nop");}
145 # define TN_ARCH_STK_ATTR_BEFORE
146 # define TN_ARCH_STK_ATTR_AFTER __attribute__((aligned(0x8)))
148 # error "Unknown compiler"
155 #define TN_MIN_STACK_SIZE (36 + _TN_STACK_OVERFLOW_SIZE_ADD)
160 #define TN_INT_WIDTH 32
181 #define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH
187 #define TN_WAIT_INFINITE (TN_TickCnt)0xFFFFFFFF
192 #define TN_FILL_STACK_VAL 0xFEEDFACE
209 #define TN_INTSAVE_DATA \
210 int tn_save_status_reg = _TN_PIC32_INTSAVE_DATA_INVALID;
219 #define TN_INTSAVE_DATA_INT TN_INTSAVE_DATA
248 # define TN_INT_DIS_SAVE() tn_save_status_reg = tn_arch_sr_save_int_dis()
249 # define TN_INT_RESTORE() _TN_PIC32_INTSAVE_CHECK(); \
250 tn_arch_sr_restore(tn_save_status_reg)
252 # define TN_INT_DIS_SAVE() __asm__ __volatile__( \
254 : "=d" (tn_save_status_reg) \
256 # define TN_INT_RESTORE() _TN_PIC32_INTSAVE_CHECK(); \
257 __builtin_mtc0(12, 0, tn_save_status_reg)
267 #define TN_INT_IDIS_SAVE() TN_INT_DIS_SAVE()
276 #define TN_INT_IRESTORE() TN_INT_RESTORE()
281 #define TN_IS_INT_DISABLED() ((__builtin_mfc0(12, 0) & 1) == 0)
286 #define _TN_CONTEXT_SWITCH_IPEND_IF_NEEDED() \
287 _tn_context_switch_pend_if_needed()
294 #define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 2)
296 #define _TN_INLINE inline
298 #define _TN_VOLATILE_WORKAROUND
300 #endif //-- DOXYGEN_SHOULD_SKIP_THIS
329 #define tn_p32_soft_isr(vec) \
330 __attribute__((__noinline__)) void _func##vec(void); \
331 void __attribute__((naked, nomips16)) \
332 __attribute__((vector(vec))) \
335 asm volatile(".set push"); \
336 asm volatile(".set mips32r2"); \
337 asm volatile(".set nomips16"); \
338 asm volatile(".set noreorder"); \
339 asm volatile(".set noat"); \
341 asm volatile("rdpgpr $sp, $sp"); \
344 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
345 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
346 asm volatile("addiu $k1, $k1, 1"); \
347 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
348 asm volatile("ori $k0, $zero, 1"); \
349 asm volatile("bne $k1, $k0, 1f"); \
352 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
353 asm volatile("sw $sp, %lo(tn_p32_user_sp)($k0)"); \
354 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
355 asm volatile("lw $sp, %lo(tn_p32_int_sp)($k0)"); \
357 asm volatile("1:"); \
359 asm volatile("addiu $sp, $sp, -92"); \
360 asm volatile("mfc0 $k1, $14"); \
361 asm volatile("mfc0 $k0, $12, 2"); \
362 asm volatile("sw $k1, 84($sp)"); \
363 asm volatile("sw $k0, 80($sp)"); \
364 asm volatile("mfc0 $k1, $12"); \
365 asm volatile("sw $k1, 88($sp)"); \
368 asm volatile("mfc0 $k0, $13"); \
369 asm volatile("ins $k1, $zero, 1, 15"); \
370 asm volatile("ext $k0, $k0, 10, 6"); \
371 asm volatile("ins $k1, $k0, 10, 6"); \
372 asm volatile("mtc0 $k1, $12"); \
375 asm volatile("sw $ra, 76($sp)"); \
376 asm volatile("sw $t9, 72($sp)"); \
377 asm volatile("sw $t8, 68($sp)"); \
378 asm volatile("sw $t7, 64($sp)"); \
379 asm volatile("sw $t6, 60($sp)"); \
380 asm volatile("sw $t5, 56($sp)"); \
381 asm volatile("sw $t4, 52($sp)"); \
382 asm volatile("sw $t3, 48($sp)"); \
383 asm volatile("sw $t2, 44($sp)"); \
384 asm volatile("sw $t1, 40($sp)"); \
385 asm volatile("sw $t0, 36($sp)"); \
386 asm volatile("sw $a3, 32($sp)"); \
387 asm volatile("sw $a2, 28($sp)"); \
388 asm volatile("sw $a1, 24($sp)"); \
389 asm volatile("sw $a0, 20($sp)"); \
390 asm volatile("sw $v1, 16($sp)"); \
391 asm volatile("sw $v0, 12($sp)"); \
392 asm volatile("sw $at, 8($sp)"); \
393 asm volatile("mfhi $v0"); \
394 asm volatile("mflo $v1"); \
395 asm volatile("sw $v0, 4($sp)"); \
398 asm volatile("la $t0, _func"#vec); \
399 asm volatile("jalr $t0"); \
400 asm volatile("sw $v1, 0($sp)"); \
403 asm volatile("lw $v1, 0($sp)"); \
404 asm volatile("lw $v0, 4($sp)"); \
405 asm volatile("mtlo $v1"); \
406 asm volatile("mthi $v0"); \
407 asm volatile("lw $at, 8($sp)"); \
408 asm volatile("lw $v0, 12($sp)"); \
409 asm volatile("lw $v1, 16($sp)"); \
410 asm volatile("lw $a0, 20($sp)"); \
411 asm volatile("lw $a1, 24($sp)"); \
412 asm volatile("lw $a2, 28($sp)"); \
413 asm volatile("lw $a3, 32($sp)"); \
414 asm volatile("lw $t0, 36($sp)"); \
415 asm volatile("lw $t1, 40($sp)"); \
416 asm volatile("lw $t2, 44($sp)"); \
417 asm volatile("lw $t3, 48($sp)"); \
418 asm volatile("lw $t4, 52($sp)"); \
419 asm volatile("lw $t5, 56($sp)"); \
420 asm volatile("lw $t6, 60($sp)"); \
421 asm volatile("lw $t7, 64($sp)"); \
422 asm volatile("lw $t8, 68($sp)"); \
423 asm volatile("lw $t9, 72($sp)"); \
424 asm volatile("lw $ra, 76($sp)"); \
426 asm volatile("di"); \
427 asm volatile("ehb"); \
430 asm volatile("lw $k0, 84($sp)"); \
431 asm volatile("mtc0 $k0, $14"); \
432 asm volatile("lw $k0, 80($sp)"); \
433 asm volatile("mtc0 $k0, $12, 2"); \
434 asm volatile("addiu $sp, $sp, 92"); \
437 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
438 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
439 asm volatile("addiu $k1, $k1, -1"); \
440 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
441 asm volatile("bne $k1, $zero, 1f"); \
442 asm volatile("lw $k1, -4($sp)"); \
445 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
446 asm volatile("sw $sp, %lo(tn_p32_int_sp)($k0)"); \
447 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
448 asm volatile("lw $sp, %lo(tn_p32_user_sp)($k0)"); \
450 asm volatile("1:"); \
451 asm volatile("wrpgpr $sp, $sp"); \
452 asm volatile("mtc0 $k1, $12"); \
453 asm volatile("eret"); \
455 asm volatile(".set pop"); \
457 } __attribute((__noinline__)) void _func##vec(void)
478 #define tn_p32_srs_isr(vec) \
479 __attribute__((__noinline__)) void _func##vec(void); \
480 void __attribute__((naked, nomips16)) \
481 __attribute__((vector(vec))) \
484 asm volatile(".set push"); \
485 asm volatile(".set mips32r2"); \
486 asm volatile(".set nomips16"); \
487 asm volatile(".set noreorder"); \
488 asm volatile(".set noat"); \
490 asm volatile("rdpgpr $sp, $sp"); \
493 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
494 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
495 asm volatile("addiu $k1, $k1, 1"); \
496 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
497 asm volatile("ori $k0, $zero, 1"); \
498 asm volatile("bne $k1, $k0, 1f"); \
501 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
502 asm volatile("sw $sp, %lo(tn_p32_user_sp)($k0)"); \
503 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
504 asm volatile("lw $sp, %lo(tn_p32_int_sp)($k0)"); \
506 asm volatile("1:"); \
508 asm volatile("addiu $sp, $sp, -20"); \
509 asm volatile("mfc0 $k1, $14"); \
510 asm volatile("mfc0 $k0, $12, 2"); \
511 asm volatile("sw $k1, 12($sp)"); \
512 asm volatile("sw $k0, 8($sp)"); \
513 asm volatile("mfc0 $k1, $12"); \
514 asm volatile("sw $k1, 16($sp)"); \
517 asm volatile("mfc0 $k0, $13"); \
518 asm volatile("ins $k1, $zero, 1, 15"); \
519 asm volatile("ext $k0, $k0, 10, 6"); \
520 asm volatile("ins $k1, $k0, 10, 6"); \
521 asm volatile("mtc0 $k1, $12"); \
524 asm volatile("mfhi $v0"); \
525 asm volatile("mflo $v1"); \
526 asm volatile("sw $v0, 4($sp)"); \
529 asm volatile("la $t0, _func"#vec); \
530 asm volatile("jalr $t0"); \
531 asm volatile("sw $v1, 0($sp)"); \
534 asm volatile("lw $v1, 0($sp)"); \
535 asm volatile("lw $v0, 4($sp)"); \
536 asm volatile("mtlo $v1"); \
537 asm volatile("mthi $v0"); \
539 asm volatile("di"); \
540 asm volatile("ehb"); \
543 asm volatile("lw $k0, 12($sp)"); \
544 asm volatile("mtc0 $k0, $14"); \
545 asm volatile("lw $k0, 8($sp)"); \
546 asm volatile("mtc0 $k0, $12, 2"); \
547 asm volatile("addiu $sp, $sp, 20"); \
550 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
551 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
552 asm volatile("addiu $k1, $k1, -1"); \
553 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
554 asm volatile("bne $k1, $zero, 1f"); \
555 asm volatile("lw $k1, -4($sp)"); \
558 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
559 asm volatile("sw $sp, %lo(tn_p32_int_sp)($k0)"); \
560 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
561 asm volatile("lw $sp, %lo(tn_p32_user_sp)($k0)"); \
563 asm volatile("1:"); \
564 asm volatile("wrpgpr $sp, $sp"); \
565 asm volatile("mtc0 $k1, $12"); \
566 asm volatile("eret"); \
568 asm volatile(".set pop"); \
570 } __attribute((__noinline__)) void _func##vec(void)
577 #define tn_soft_isr tn_p32_soft_isr
583 #define tn_srs_isr tn_p32_srs_isr
589 #endif // _TN_ARCH_PIC32_H
void * tn_p32_user_sp
saved task stack pointer.
volatile int tn_p32_int_nest_count
current interrupt nesting count.
void * tn_p32_int_sp
saved ISR stack pointer.
unsigned int TN_UIntPtr
Unsigned integer type that is able to store pointers.
Atomic bit-field access macros for PIC24/dsPIC.
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.