当前位置:   article > 正文

TriCore: 从RTOS内核的角度看CSA

TriCore: 从RTOS内核的角度看CSA

今天尝试从RTOS内核的角度来看看 TriCore 的 CSA。

CSA的细节信息可以参考前一篇文章 TriCore User Manual 笔记 1-CSDN博客

CSA 的全称是 Context Save Area,顾名思义就是专门用来保存上下文的一块存储区域。

既然是上下文使用,那必然要求低延迟,因此一般将其部署在 fast ram 区域,具体到 TriCore 中,一般将其置于 DSPR 区域。在使用时,在内核启动之前,要将用作 CSA 的内存区域进行初始化,将其串成一个 Free CSA List,并将该区域的首尾地址分别赋值给 FCX 和 LCX 两个 CSA 寄存器,保证程序运行时能正常通过两个寄存器使用 Free CSA List。然后在创建任务时,为每个任务分配初始 CSA,保存任务初始运行状态信息。

下面,结合 Aurix Studio IDEFreeRTOS 来看下上面所说的每一步分别怎么实现。

1. 部署 csa,放置到 DSPR 区域

  1. #define LCF_DSPR0_SIZE 240k
  2. #define LCF_CSA0_OFFSET (LCF_DSPR0_SIZE - 1k - LCF_CSA0_SIZE)
  3. memory dsram0 // Data Scratch Pad Ram
  4. {
  5. mau = 8;
  6. size = 240k;
  7. type = ram;
  8. map (dest=bus:tc0:fpi_bus, dest_offset=0xd0000000, size=240k, priority=8);
  9. map (dest=bus:sri, dest_offset=0x70000000, size=240k);
  10. }
  11. group (ordered)
  12. {
  13. // 将 CORE0 CSA 部署到 DSPR 区域
  14. group (align = 64, attributes=rw, run_addr=mem:dsram0[LCF_CSA0_OFFSET])
  15. reserved "csa_tc0" (size = LCF_CSA0_SIZE);
  16. "__CSA0":= "_lc_ub_csa_tc0";
  17. "__CSA0_END":= "_lc_ue_csa_tc0";
  18. }

2. 初始化 CSA, 创建 Free CSA List,并初始化 FCX 和 LCX 寄存器

  1. #define IFX_SSW_INIT_CONTEXT() \
  2. { \
  3. /* Load user stack pointer */ \
  4. Ifx_Ssw_setAddressReg(a10, __USTACK(0)); \
  5. Ifx_Ssw_DSYNC(); \
  6. \
  7. /*Initialize the context save area for CPU0. Function Calls Possible */ \
  8. /* Setup the context save area linked list */ \
  9. Ifx_Ssw_initCSA((unsigned int *)__CSA(0), (unsigned int *)__CSA_END(0)); \
  10. /* Clears any instruction buffer */ \
  11. Ifx_Ssw_ISYNC(); \
  12. }
  13. IFX_SSW_INLINE void Ifx_Ssw_initCSA(unsigned int *csaBegin, unsigned int *csaEnd)
  14. {
  15. unsigned int k;
  16. unsigned int nxt_cxi_val = 0U;
  17. unsigned int *prvCsa = 0U;
  18. unsigned int *nxtCsa = csaBegin;
  19. unsigned int numOfCsa = (((unsigned int)csaEnd - (unsigned int)csaBegin) / 64U);
  20. for (k = 0U; k < numOfCsa; k++)
  21. {
  22. nxt_cxi_val = ((unsigned int)((unsigned int)nxtCsa & ((unsigned int)0XFU << 28U)) >> 12U) | \
  23. ((unsigned int)((unsigned int)nxtCsa & ((unsigned int)0XFFFFU << 6U)) >> 6U);
  24. if (k == 0U)
  25. {
  26. Ifx_Ssw_MTCR(CPU_FCX, nxt_cxi_val); /* store the new pcxi value to LCX */
  27. }
  28. else
  29. {
  30. *prvCsa = nxt_cxi_val;
  31. }
  32. if (k == (numOfCsa - 3U))
  33. {
  34. Ifx_Ssw_MTCR(CPU_LCX, nxt_cxi_val); /* Last but 2 context save area is pointed in LCX to know if there is CSA depletion */
  35. }
  36. prvCsa = (unsigned int *)nxtCsa;
  37. nxtCsa += IFX_SSW_CSA_SIZE; /* next CSA */
  38. }
  39. *prvCsa = 0U; /* Store null pointer in last CSA (= very first time!) */
  40. Ifx_Ssw_DSYNC();
  41. }

3. 创建任务时分配csa

  1. StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
  2. TaskFunction_t pxCode,
  3. void * pvParameters )
  4. {
  5. uint32_t * pulUpperCSA = NULL;
  6. uint32_t * pulLowerCSA = NULL;
  7. /* 16 Address Registers (4 Address registers are global), 16 Data
  8. * Registers, and 3 System Registers.
  9. *
  10. * There are 3 registers that track the CSAs.
  11. * FCX points to the head of globally free set of CSAs.
  12. * PCX for the task needs to point to Lower->Upper->NULL arrangement.
  13. * LCX points to the last free CSA so that corrective action can be taken.
  14. *
  15. * Need two CSAs to store the context of a task.
  16. * The upper context contains D8-D15, A10-A15, PSW and PCXI->NULL.
  17. * The lower context contains D0-D7, A2-A7, A11 and PCXI->UpperContext.
  18. * The pxCurrentTCB->pxTopOfStack points to the Lower Context RSLCX matching the initial BISR.
  19. * The Lower Context points to the Upper Context ready for the return from the interrupt handler.
  20. *
  21. * The Real stack pointer for the task is stored in the A10 which is restored
  22. * with the upper context. */
  23. /* Have to disable interrupts here because the CSAs are going to be
  24. * manipulated. */
  25. portENTER_CRITICAL();
  26. {
  27. /* DSync to ensure that buffering is not a problem. */
  28. _dsync();
  29. /* Consume two free CSAs. */
  30. pulLowerCSA = portCSA_TO_ADDRESS( __MFCR( $FCX ) );
  31. if( NULL != pulLowerCSA )
  32. {
  33. /* The Lower Links to the Upper. */
  34. pulUpperCSA = portCSA_TO_ADDRESS( pulLowerCSA[ 0 ] );
  35. }
  36. /* Check that we have successfully reserved two CSAs. */
  37. if( ( NULL != pulLowerCSA ) && ( NULL != pulUpperCSA ) )
  38. {
  39. /* Remove the two consumed CSAs from the free CSA list. */
  40. _disable();
  41. _dsync();
  42. _mtcr( $FCX, pulUpperCSA[ 0 ] );
  43. _isync();
  44. _enable();
  45. }
  46. else
  47. {
  48. /* Simply trigger a context list depletion trap. */
  49. _svlcx();
  50. }
  51. }
  52. portEXIT_CRITICAL();
  53. /* Clear the upper CSA. */
  54. memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) );
  55. /* Upper Context. */
  56. pulUpperCSA[ 2 ] = ( uint32_t ) pxTopOfStack; /* A10; Stack Return aka Stack Pointer */
  57. pulUpperCSA[ 1 ] = portSYSTEM_PROGRAM_STATUS_WORD; /* PSW */
  58. /* Clear the lower CSA. */
  59. memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) );
  60. /* Lower Context. */
  61. pulLowerCSA[ 8 ] = ( uint32_t ) pvParameters; /* A4; Address Type Parameter Register */
  62. pulLowerCSA[ 1 ] = ( uint32_t ) pxCode; /* A11; Return Address aka RA */
  63. /* PCXI pointing to the Upper context. */
  64. pulLowerCSA[ 0 ] = ( portINITIAL_PCXI_UPPER_CONTEXT_WORD | ( uint32_t ) portADDRESS_TO_CSA( pulUpperCSA ) );
  65. /* Save the link to the CSA in the top of stack. */
  66. pxTopOfStack = ( uint32_t * ) portADDRESS_TO_CSA( pulLowerCSA );
  67. /* DSync to ensure that buffering is not a problem. */
  68. _dsync();
  69. return pxTopOfStack;
  70. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/570611
推荐阅读
相关标签
  

闽ICP备14008679号