45 #ifndef _TN_ARCH_PIC32_H
46 #define _TN_ARCH_PIC32_H
53 #include "../../core/tn_cfg_dispatch.h"
86 #ifndef DOXYGEN_SHOULD_SKIP_THIS
88 #define _TN_PIC32_INTSAVE_DATA_INVALID 0xffffffff
91 # define _TN_PIC32_INTSAVE_CHECK() \
93 if (tn_save_status_reg == _TN_PIC32_INTSAVE_DATA_INVALID){ \
94 _TN_FATAL_ERROR(""); \
98 # define _TN_PIC32_INTSAVE_CHECK()
107 #define _TN_FFS(x) (32 - __builtin_clz((x) & (0 - (x))))
116 #define _TN_FATAL_ERROR(error_msg, ...) \
117 {__asm__ volatile(" sdbbp 0"); __asm__ volatile ("nop");}
144 # define TN_ARCH_STK_ATTR_BEFORE
145 # define TN_ARCH_STK_ATTR_AFTER __attribute__((aligned(0x8)))
147 # error "Unknown compiler"
154 #define TN_MIN_STACK_SIZE 36
159 #define TN_INT_WIDTH 32
180 #define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH
186 #define TN_WAIT_INFINITE (TN_Timeout)0xFFFFFFFF
191 #define TN_FILL_STACK_VAL 0xFEEDFACE
208 #define TN_INTSAVE_DATA \
209 int tn_save_status_reg = _TN_PIC32_INTSAVE_DATA_INVALID;
218 #define TN_INTSAVE_DATA_INT TN_INTSAVE_DATA
247 # define TN_INT_DIS_SAVE() tn_save_status_reg = tn_arch_sr_save_int_dis()
248 # define TN_INT_RESTORE() _TN_PIC32_INTSAVE_CHECK(); \
249 tn_arch_sr_restore(tn_save_status_reg)
251 # define TN_INT_DIS_SAVE() __asm__ __volatile__( \
253 : "=d" (tn_save_status_reg) \
255 # define TN_INT_RESTORE() _TN_PIC32_INTSAVE_CHECK(); \
256 __builtin_mtc0(12, 0, tn_save_status_reg)
266 #define TN_INT_IDIS_SAVE() TN_INT_DIS_SAVE()
275 #define TN_INT_IRESTORE() TN_INT_RESTORE()
280 #define TN_IS_INT_DISABLED() ((__builtin_mfc0(12, 0) & 1) == 0)
285 #define _TN_CONTEXT_SWITCH_IPEND_IF_NEEDED() \
286 _tn_context_switch_pend_if_needed()
293 #define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 2)
297 #endif //-- DOXYGEN_SHOULD_SKIP_THIS
326 #define tn_p32_soft_isr(vec) \
327 __attribute__((__noinline__)) void _func##vec(void); \
328 void __attribute__((naked, nomips16)) \
329 __attribute__((vector(vec))) \
332 asm volatile(".set push"); \
333 asm volatile(".set mips32r2"); \
334 asm volatile(".set nomips16"); \
335 asm volatile(".set noreorder"); \
336 asm volatile(".set noat"); \
338 asm volatile("rdpgpr $sp, $sp"); \
341 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
342 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
343 asm volatile("addiu $k1, $k1, 1"); \
344 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
345 asm volatile("ori $k0, $zero, 1"); \
346 asm volatile("bne $k1, $k0, 1f"); \
349 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
350 asm volatile("sw $sp, %lo(tn_p32_user_sp)($k0)"); \
351 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
352 asm volatile("lw $sp, %lo(tn_p32_int_sp)($k0)"); \
354 asm volatile("1:"); \
356 asm volatile("addiu $sp, $sp, -92"); \
357 asm volatile("mfc0 $k1, $14"); \
358 asm volatile("mfc0 $k0, $12, 2"); \
359 asm volatile("sw $k1, 84($sp)"); \
360 asm volatile("sw $k0, 80($sp)"); \
361 asm volatile("mfc0 $k1, $12"); \
362 asm volatile("sw $k1, 88($sp)"); \
365 asm volatile("mfc0 $k0, $13"); \
366 asm volatile("ins $k1, $zero, 1, 15"); \
367 asm volatile("ext $k0, $k0, 10, 6"); \
368 asm volatile("ins $k1, $k0, 10, 6"); \
369 asm volatile("mtc0 $k1, $12"); \
372 asm volatile("sw $ra, 76($sp)"); \
373 asm volatile("sw $t9, 72($sp)"); \
374 asm volatile("sw $t8, 68($sp)"); \
375 asm volatile("sw $t7, 64($sp)"); \
376 asm volatile("sw $t6, 60($sp)"); \
377 asm volatile("sw $t5, 56($sp)"); \
378 asm volatile("sw $t4, 52($sp)"); \
379 asm volatile("sw $t3, 48($sp)"); \
380 asm volatile("sw $t2, 44($sp)"); \
381 asm volatile("sw $t1, 40($sp)"); \
382 asm volatile("sw $t0, 36($sp)"); \
383 asm volatile("sw $a3, 32($sp)"); \
384 asm volatile("sw $a2, 28($sp)"); \
385 asm volatile("sw $a1, 24($sp)"); \
386 asm volatile("sw $a0, 20($sp)"); \
387 asm volatile("sw $v1, 16($sp)"); \
388 asm volatile("sw $v0, 12($sp)"); \
389 asm volatile("sw $at, 8($sp)"); \
390 asm volatile("mfhi $v0"); \
391 asm volatile("mflo $v1"); \
392 asm volatile("sw $v0, 4($sp)"); \
395 asm volatile("la $t0, _func"#vec); \
396 asm volatile("jalr $t0"); \
397 asm volatile("sw $v1, 0($sp)"); \
400 asm volatile("lw $v1, 0($sp)"); \
401 asm volatile("lw $v0, 4($sp)"); \
402 asm volatile("mtlo $v1"); \
403 asm volatile("mthi $v0"); \
404 asm volatile("lw $at, 8($sp)"); \
405 asm volatile("lw $v0, 12($sp)"); \
406 asm volatile("lw $v1, 16($sp)"); \
407 asm volatile("lw $a0, 20($sp)"); \
408 asm volatile("lw $a1, 24($sp)"); \
409 asm volatile("lw $a2, 28($sp)"); \
410 asm volatile("lw $a3, 32($sp)"); \
411 asm volatile("lw $t0, 36($sp)"); \
412 asm volatile("lw $t1, 40($sp)"); \
413 asm volatile("lw $t2, 44($sp)"); \
414 asm volatile("lw $t3, 48($sp)"); \
415 asm volatile("lw $t4, 52($sp)"); \
416 asm volatile("lw $t5, 56($sp)"); \
417 asm volatile("lw $t6, 60($sp)"); \
418 asm volatile("lw $t7, 64($sp)"); \
419 asm volatile("lw $t8, 68($sp)"); \
420 asm volatile("lw $t9, 72($sp)"); \
421 asm volatile("lw $ra, 76($sp)"); \
423 asm volatile("di"); \
424 asm volatile("ehb"); \
427 asm volatile("lw $k0, 84($sp)"); \
428 asm volatile("mtc0 $k0, $14"); \
429 asm volatile("lw $k0, 80($sp)"); \
430 asm volatile("mtc0 $k0, $12, 2"); \
431 asm volatile("addiu $sp, $sp, 92"); \
434 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
435 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
436 asm volatile("addiu $k1, $k1, -1"); \
437 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
438 asm volatile("bne $k1, $zero, 1f"); \
439 asm volatile("lw $k1, -4($sp)"); \
442 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
443 asm volatile("sw $sp, %lo(tn_p32_int_sp)($k0)"); \
444 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
445 asm volatile("lw $sp, %lo(tn_p32_user_sp)($k0)"); \
447 asm volatile("1:"); \
448 asm volatile("wrpgpr $sp, $sp"); \
449 asm volatile("mtc0 $k1, $12"); \
450 asm volatile("eret"); \
452 asm volatile(".set pop"); \
454 } __attribute((__noinline__)) void _func##vec(void)
475 #define tn_p32_srs_isr(vec) \
476 __attribute__((__noinline__)) void _func##vec(void); \
477 void __attribute__((naked, nomips16)) \
478 __attribute__((vector(vec))) \
481 asm volatile(".set push"); \
482 asm volatile(".set mips32r2"); \
483 asm volatile(".set nomips16"); \
484 asm volatile(".set noreorder"); \
485 asm volatile(".set noat"); \
487 asm volatile("rdpgpr $sp, $sp"); \
490 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
491 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
492 asm volatile("addiu $k1, $k1, 1"); \
493 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
494 asm volatile("ori $k0, $zero, 1"); \
495 asm volatile("bne $k1, $k0, 1f"); \
498 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
499 asm volatile("sw $sp, %lo(tn_p32_user_sp)($k0)"); \
500 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
501 asm volatile("lw $sp, %lo(tn_p32_int_sp)($k0)"); \
503 asm volatile("1:"); \
505 asm volatile("addiu $sp, $sp, -20"); \
506 asm volatile("mfc0 $k1, $14"); \
507 asm volatile("mfc0 $k0, $12, 2"); \
508 asm volatile("sw $k1, 12($sp)"); \
509 asm volatile("sw $k0, 8($sp)"); \
510 asm volatile("mfc0 $k1, $12"); \
511 asm volatile("sw $k1, 16($sp)"); \
514 asm volatile("mfc0 $k0, $13"); \
515 asm volatile("ins $k1, $zero, 1, 15"); \
516 asm volatile("ext $k0, $k0, 10, 6"); \
517 asm volatile("ins $k1, $k0, 10, 6"); \
518 asm volatile("mtc0 $k1, $12"); \
521 asm volatile("mfhi $v0"); \
522 asm volatile("mflo $v1"); \
523 asm volatile("sw $v0, 4($sp)"); \
526 asm volatile("la $t0, _func"#vec); \
527 asm volatile("jalr $t0"); \
528 asm volatile("sw $v1, 0($sp)"); \
531 asm volatile("lw $v1, 0($sp)"); \
532 asm volatile("lw $v0, 4($sp)"); \
533 asm volatile("mtlo $v1"); \
534 asm volatile("mthi $v0"); \
536 asm volatile("di"); \
537 asm volatile("ehb"); \
540 asm volatile("lw $k0, 12($sp)"); \
541 asm volatile("mtc0 $k0, $14"); \
542 asm volatile("lw $k0, 8($sp)"); \
543 asm volatile("mtc0 $k0, $12, 2"); \
544 asm volatile("addiu $sp, $sp, 20"); \
547 asm volatile("lui $k0, %hi(tn_p32_int_nest_count)"); \
548 asm volatile("lw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
549 asm volatile("addiu $k1, $k1, -1"); \
550 asm volatile("sw $k1, %lo(tn_p32_int_nest_count)($k0)"); \
551 asm volatile("bne $k1, $zero, 1f"); \
552 asm volatile("lw $k1, -4($sp)"); \
555 asm volatile("lui $k0, %hi(tn_p32_int_sp)"); \
556 asm volatile("sw $sp, %lo(tn_p32_int_sp)($k0)"); \
557 asm volatile("lui $k0, %hi(tn_p32_user_sp)"); \
558 asm volatile("lw $sp, %lo(tn_p32_user_sp)($k0)"); \
560 asm volatile("1:"); \
561 asm volatile("wrpgpr $sp, $sp"); \
562 asm volatile("mtc0 $k1, $12"); \
563 asm volatile("eret"); \
565 asm volatile(".set pop"); \
567 } __attribute((__noinline__)) void _func##vec(void)
574 #define tn_soft_isr tn_p32_soft_isr
580 #define tn_srs_isr tn_p32_srs_isr
586 #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.
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.