FreeRTOSの雇用創出、スケジューラ、タスク切り替えプロセス分析を開始 - ベースTricore1.6

タスクの[作成]

タスク制御ブロックTCBを作成します。1.

2.タスクとタスク制御ブロック(pxNewTCB-> pxStack = pxStack)に格納された開始アドレスのためのアプリケーション・スタック・スペース

3.コールprvInitialiseNewTask()関数

  1)スタックポインタpxTopOfStack NewTCB.pxStackによって計算され、整列されます。

  2)タスク名や優先度情報を記録(pxNewTCB-> pcTaskName、pxNewTCB-> uxPriority ...)

  3)コールpxPortInitialiseStack()関数)が正確CSAであること(タスクスタックを初期化します

    CPU_FCXコンテキストポインタと割り当てられた下部pulLowerCSAから空きアドレスレジスタCSAを取得します

    取得したリンクの言葉によると、次の空きCSAのCSAのアドレスを検索し、ハイレベルのコンテキストポインタpulUpperCSAに割り当てられました

    最新の無料CSAを指すように更新値CPU_FCX

    CSAセットのシニアコンテキスト:

      空CSA、今後の高レベルの全体の内容が0に設定されているのCSAコンテキスト

      ワードに対応するスタックポインタpxTopOfStack A [10](SP)は、タスクのスタックの適用前に設定されています

      portSYSTEM_PROGRAM_STATUS_WORDに対応するワードPSW

    コンテキストのCSA低く設定:

      空CSA、すなわち0にCSAセットの下内容の全体コンテキスト

      対応する単語セットタスクパラメータpvParametersにA [4]

      ワードアドレスに対応するA [11](RA)は、タスク関数pxCodeに設定されています

    高度なコンテキストアドレスのCSAのCSAの文脈におけるリンク単語PCXIセット低

    そして、CSAのアドレスpxTopOfStack低リターンコンテキストの値を設定します

  4)TCBアドレス記憶pxNewTCB-> pxTopOfStack = pxPortInitialiseStack(pxTopOfStack、pxTaskCode、pvParameters)の下部CSAコンテキスト。

  5)削除操作タスクのタスク制御ブロックへのハンドルを返します。

タスクレディリストに追加良い仕事を作成します。4.

 

[スタート]スケジューラ

1.設定STM、STMこじ開けるとインストール

トラップ・ハンドラの2.インストールのsyscall(0)

ソフトウェア割り込みの割り込みGPSR00汎用レジスタをインストール3。

4. PSWレジスタとレジスタを初期化SYSCON

; _mtcr(CPU_PCXI、* pxCurrentTCB):現在のコンテキストCSA pxCurrentTCBタスク制御ブロックおよび譲受人のPCXIから読み出しアドレス下位

6. _rslcx命令実行、下部コンテキストCSA PCXからの指示は、より低い回復コンテキスト(値はCSAリンクワード格納されたリンクワードに更新された後に実行PCX命令、すなわちCSA高度コンテキストのアドレス、CSAおよび尖ったFCX)リスト中に放出されます

7. RFE命令実行、Aへの復帰[11](RA)高度コンテキスト回復(両方並列実行)しながら、リターンアドレスを格納します。入力された実行機能RFE後タスク関数の値、従ってタスク、すなわち、最初のタスクの開始に対応するアドレスA [11]におけるCSAの初期化タスクの作成。

 

[タスクの切り替え]

タスクを切り替えるには3つの方法があります。

(1)タスク呼び出しタスクカット

  スイッチング機能:portYIELD()/ portYIELD_WITHIN_API()/ taskYEILD()

  プロセッサリソース:Trap_class6_TIN0

  トリガー:_syscall(0)

(2)通常のタスクは、割り込み通話を切り替えます

  スイッチング機能:portYIELD_FROM_ISR()/ taskYEILD_FROM_ISR()

  プロセッサリソース:GPSRx0

  トリガー:GPSRx0.B.SETR = 1またはINT_SRB0.B.TRIG0 = 1

タスク切り替え(3)のSysTick中断中

  切替機能:StmISRに

  プロセッサリソース:SysTimerx

  トリガー:SysTimerx COMP0カウンタのオーバーフロー割り込みトリガ

3 port.c割り込みまたはトラップハンドラにこれらの三つのタスクスイッチングモード対応:prvTrapYield()、prvInterruptYield()、prvSystemTickHandler()。この操作は、3つの処理機能を実行されます。

  _disable(); //割り込み禁止

  _dsync()。

  xUpperCSA = _mfcr(CPU_PCXI); //は、レジスタPCXIの値を取得

  pxUpperCSA = portCSA_TO_ADDRESS(xUpperCSA); //はCSAとPCXOアドレスフィールド点にPCXS PCXI変換PCX

  * PxCurrentTCB = pxUpperCSA [0]; // PCX現在、現在のタスクTCB.TopOfStackに、すなわち次CSAリンクワードアドレス記憶CSA指さ

  vTaskSwitchContext(); //新しい仕事を探して、更新された値pxCurrentTCB

  pxUpperCSA [0] = * pxCurrentTCB; //ポイントへの新しいタスクの現在のCSA PCXリンクワードはアドレスCSA(下位コンテキストアドレス)に設定されます

  SRC_GPSR00.B.SRR = 0;                  

  _isync()。

多くの質問がありますここを参照してください:

保存しないのはなぜ現在のタスクの低コンテキスト(1)?

(2)なぜ、むしろLowerCSAよりも、UpperCSAと呼ばれる店舗PCXIの価値は変数?

(3)なぜ格納されTCB.TopOfStack pxUpperCSA [0]、すなわち現在のCSAリンクワードの値の代わりにpxUpperCSA

コンテキスト(4)新しいタスクはなぜ回復していませんか?

新しいタスクに切り替えて実行する方法(5)?

割り込みやトラップコードを分析した後、次のような答えを描きます:

下部コンテキスト(1)現在のタスクが保存されていないではないが、割り込みまたはトラップハンドラに書き込まれていない、次のように動作セーブ下部コンテキストが(割り込みまたはトラップエントリ手順で行われている割込みエントリー手順を参照するか、またはトラップベクター(テーブル)ボーエン「原理の一連のTriCore MCU割込みシステム」を参照し、ハンドラジャンプにコードのセクションに格納されています)。割り込みプログラムのエントリでBISRトラップの入口で使用される低コンテキストを保存するための完全な命令、および手続きsvlcxの下のコンテキストを保存する命令完了。

cint_tc29x.cは、割り込みやトラップの入り口を定義しました。

(2)この時点で、PCXは、続いて、タスクの現在のコンテキストを保存した後、下部のように、実際にCSAの高レベルのコンテキストでコール自動的に保存高度の文脈で発生ハンドラ、したがってこの時点でPCXを呼び出すための命令CSAポイントは、ハンドラの前に、高度なコンテキストを入力します。

(3)現在の点ので、PCXは、高レベルのコンテキスト・CSA、現在のタスクのコンテキストと高度CSAのCSAの文脈におけるリヤロアリンク構造でPCX-> BeforeHandlerUpperCSA-> TaskLowerCSA-> TaskUpperCSA、TCB.TopOfStack = pxUpperCSAので、[0]これは、TCBにTaskLowerCSAアドレスを格納しています。保存PCX、状況のFCXのCSAリストと変更後の状況は下記のように。

 

 

(4)pxUpperCSA[ 0 ] = *pxCurrentTCB 所做的是将新任务的LowerCSA和UpperCSA链接到BeforeHandlerUpperCSA后面,即PCX->BeforeHandlerUpperCSA->NewTaskLowerCSA->NewTaskUpperCSA,当该中断或陷阱处理函数执行完成后返回时,会自动恢复高级上下文并释放BeforeHandlerUpperCSA到FCX所指向的列表中,此时PCX就指向了新任务的CSA,即PCX->NewTaskLowerCSA->NewTaskUpperCSA,具体过程如下图所示。从处理函数返回后会执行rslcxrfe指令,分别恢复新任务的低级上下文和高级上下文

 

 

(5)执行rfe指令时会从A[11](RA)寄存器获取返回地址,而此时A[11]的值为新任务的任务函数地址,于是便跳转到了新任务函数。(高级上下文的恢复与向返回地址的跳转是并行的)

 

 

以上便是FreeRTOS创建任务、启动调度器、切换任务的整个过程的原理及实现,都是与移植相关的,都涉及到内核架构方面的知识,不容易看懂。

----------------------------------------------------------------------------------------------------------------------

最后补充一点:在使用iLLD时,中断和陷阱入口程序的定义与cint_tc29x.c不同,因此任务切换的过程也可能有所不同。

陷阱的入口程序的定义与之前所述的基本相同,其定义如下图所示:

 

这里使用了ji指令进行了直接跳转,因此不自动保存高级上下文,而在钩子函数(内联函数,不属于函数调用,不发生上下文自动保存)中调用了陷阱处理函数prvTrapYield(),因此发生一次高级上下文的自动保存。从prvTrapYield()函数中返回时恢复了该高级上下文,接着执行rslcx和rfe指令恢复新任务的上下文并跳转到任务函数中继续执行。

但中断入口程序的定义有所不同,我们首先从软件管理的中断开始分析,入口程序的定义如下:

将宏IFX_INTERRUPT_INTERNAL展开后得到:

这里在入口处保存了低级上下文,然后使用ji指令直接跳转到了IfxCpu_Irq_intVecTable()函数,该函数中调用了相应的中断处理程序(prvSystemTickHandler或prvInterruptYield),因此产生了一次高级上下文的保存,进入任务切换函数后的处理过程不再赘述。到这里有一个问题:为什么入口程序中没有rslcx和rfe指令?但实际上FreeRTOS能够正常运行。于是开始对程序进行调试,调试的过程中发现编译器自动在IfxCpu_Irq_intVecTable()函数的末尾添加了这两条指令,如图所示:

 

 为什么编译器会自动添加这两条指令呢?通过HighTec编译器的用户手册发现了原因:

这样的话一切就说的通了!

接下来我们再对硬件管理的中断进行分析。硬件管理方式中,中断向量的内容即中断入口程序和软件管理方式是一样的,如下图所示。但不同于软件管理中断的单一中断向量,硬件管理方式下每个中断对应一个中断向量。中断发生时先自动保存高级上下文,然后进入中断入口程序,入口程序首先保存低级上下文,然后直接跳转到中断处理函数,而不像软件管理方式间接通过函数IfxCpu_Irq_intVecTable()进行相应中断处理函数的调用。但是这也导致使用硬件中断时,任务切换函数需要修改,否则会发生上下文保存与恢复上的错误,因为硬件中断是使用ji指令直接跳转到中断处理函数prvSystemTickHandler或prvInterruptYield中的,并没有发生高级上下文的保存,因此CSA、PCX和FCX的状态为PCX->TaskLowerCSA->TaskUpperCSA,与前文中的状态不一致。

 

おすすめ

転載: www.cnblogs.com/uestcliming666/p/12411949.html