FreeRTOS 移植要点(2)
port.c port.c 中主要实现了几个函数: pxPortInitialiseStack() xPortStartScheduler() vPortEndScheduler() vPortYield() vPortTickInterrupt() 还定义了个全局变量:uxCriticalNesting uxCriticalNesting 定义全局变量uxCriticalNesting 的代码如下。 /*
port.c
port.c 中主要实现了几个函数:
pxPortInitialiseStack()
xPortStartScheduler()
vPortEndScheduler()
vPortYield()
vPortTickInterrupt()
还定义了个全局变量:uxCriticalNesting
uxCriticalNesting
定义全局变量uxCriticalNesting 的代码如下。
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the critical div should not be left (i.e. interrupts should not be re-enabled) until the nesting depth reaches 0. This variable simply tracks the nesting depth. Each task maintains it's own critical nesting depth variable so uxCriticalNesting is saved and restored from the task stack during a context switch. */ volatile unsigned portBASE_TYPE uxCriticalNesting = 0xff;
uxCriticalNesting 的初始值并不重要,因为每个任务的堆栈中存了uxCriticalNesting 各自的初始值0。
pxPortInitialiseStack
第一个介绍的是pxPortInitialiseStack()。这个函数的作用与uC/OS-II 中 OS_STK*OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) 函数的作用是相同的,实现代码也大同小异。
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) { /* Place a few bytes of known values on the bottom of the stack. This can be uncommented to provide useful stack markers when debugging. *pxTopOfStack = ( portSTACK_TYPE ) 0x11; pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) 0x22; pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) 0x33; pxTopOfStack--; */ /* Setup the initial stack of the task. The stack is set exactly as expected by the portRESTORE_CONTEXT() macro. In this case the stack as expected by the HCS12 RTI instruction. */ /* The address of the task function is placed in the stack byte at a time. */ *pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pxCode) ) + 1 ); pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pxCode) ) + 0 ); pxTopOfStack--; /* Next are all the registers that form part of the task context. */ /* Y register */ *pxTopOfStack = ( portSTACK_TYPE ) 0xff; pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) 0xee; pxTopOfStack--; /* X register */ *pxTopOfStack = ( portSTACK_TYPE ) 0xdd; pxTopOfStack--; *pxTopOfStack = ( portSTACK_TYPE ) 0xcc; pxTopOfStack--; /* A register contains parameter high byte. */ *pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pvParameters) ) + 0 ); pxTopOfStack--; /* B register contains parameter low byte. */ *pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pvParameters) ) + 1 ); pxTopOfStack--; /* CCR: Note that when the task starts interrupts will be enabled since "I" bit of CCR is cleared */ *pxTopOfStack = ( portSTACK_TYPE ) 0x00; pxTopOfStack--; #ifdef BANKED_MODEL /* The page of the task. */ *pxTopOfStack = ( portSTACK_TYPE ) ( ( int ) pxCode ); pxTopOfStack--; #endif /* Finally the critical nesting depth is initialised with 0 (not within a critical div). */ *pxTopOfStack = ( portSTACK_TYPE ) 0x00; return pxTopOfStack; }
xPortStartScheduler
xPortStartScheduler()函数对应于uC/OS-II 中的OSStartHighRdy() 函数。FreeRTOS的移植代码中并没有直接在xPortStartScheduler() 函数中实现具体功能,而是将真正的工作放到了xBankedStartScheduler()函数中,xPortStartScheduler()函数只是简单的调用xBankedStartScheduler()函数。之所以这样处理是因为相应的代码需放到64K以内的地址空间中。具体可以参看下面代码中的注释部分。
#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Simply called by xPortStartScheduler(). xPortStartScheduler() does not start the scheduler directly because the header file containing the xPortStartScheduler() prototype is part of the common kernel code, and therefore cannot use the CODE_SEG pragma. */ static portBASE_TYPE xBankedStartScheduler( void ); #pragma CODE_SEG DEFAULT portBASE_TYPE xPortStartScheduler( void ) { /* xPortStartScheduler() does not start the scheduler directly because the header file containing the xPortStartScheduler() prototype is part of the common kernel code, and therefore cannot use the CODE_SEG pragma. Instead it simply calls the locally defined xBankedStartScheduler() - which does use the CODE_SEG pragma. */ return xBankedStartScheduler(); } /*-----------------------------------------------------------*/ #pragma CODE_SEG __NEAR_SEG NON_BANKED static portBASE_TYPE xBankedStartScheduler( void ) { /* Configure the timer that will generate the RTOS tick. Interrupts are disabled when this function is called. */ prvSetupTimerInterrupt(); /* Restore the context of the first task. */ portRESTORE_CONTEXT(); /* Simulate the end of an interrupt to start the scheduler off. */ __asm( "rti" ); /* Should not get here! */ return pdFALSE; }
上面代码中调用了prvSetupTimerInterrupt() 函数,这在 uC/OS-II中是没有对应代码的。prvSetupTimerInterrupt()函数的功能是设置定时中断的频率。在这里放这个函数从程序逻辑上来看并不是太好。我本人还是倾向于uC/OS-II 作者的做法,应该将prvSetupTimerInterrupt() 函数放到第一个运行的任务的代码中,虽然这里的做法也没错误。
vPortEndScheduler
这个函数在uC/OS-II 没有对应的函数,因为uC/OS-II 不允许退出。这个移植代码中也没有实现什么具体的功能,就是个空函数。
void vPortEndScheduler( void ) { /* It is unlikely that the HCS12 port will get stopped. */ }
vPortYield
vPortYield()函数等价于uC/OS-II 中的OSCtxSw()函数。具体代码如下:
/* * Manual context switch forced by calling portYIELD(). This is the SWI * handler. */ void interrupt vPortYield( void ) { portSAVE_CONTEXT(); vTaskSwitchContext(); portRESTORE_CONTEXT(); }
FreeRTOS中少了与 uC/OS-II 中 OSIntCtxSw()函数对应的函数,这时因为FreeRTOS 中相应的功能用一个宏定义来实现了:portRESTORE_CONTEXT() ,因此就不需要这个函数了。
vPortTickInterrupt()
最后一个函数是vPortTickInterrupt() 这个函数是定时中断处理函数,等价于uC/OS-II 移植代码中的:interrupt VectorNumber_Vrti void OSTickISR (void)
由于 FreeRTOS既支持抢占式多任务,也支持协作式多任务,所以vPortTickInterrupt()函数相对uC/OS-II 移植代码中的OSTickISR()来说要复杂些。
/* * RTOS tick interrupt service routine. If the cooperative scheduler is * being used then this simply increments the tick count. If the * preemptive scheduler is being used a context switch can occur. */ void interrupt vPortTickInterrupt( void ) { #if configUSE_PREEMPTION == 1 { /* A context switch might happen so save the context. */ portSAVE_CONTEXT(); /* Increment the tick ... */ vTaskIncrementTick(); /* ... then see if the new tick value has necessitated a context switch. */ vTaskSwitchContext(); TFLG1 = 1; /* Restore the context of a task - which may be a different task to that interrupted. */ portRESTORE_CONTEXT(); } #else { vTaskIncrementTick(); TFLG1 = 1; } #endif }
至此,所有移植代码就都分析完了。
实时操作系统内核其实都大同小异,掌握了一种再学习其余的很容易就能入门。从入门难度来说,uC/OS-II无疑是入门学习的首选。之所以这么说并不是因为uC/OS-II本身很简单,而是国内介绍uC/OS-II的资料非常多。相比起来,介绍FreeRTOS的资料就少的可怜了。我建议想要学习FreeRTOS的人还是应该先学习uC/OS-II,学懂了uC/OS-II,然后对比着学习FreeRTOS,这样会事半功倍。这也是我学习FreeRTOS的路径。

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Bagaimana untuk melaksanakan log masuk WeChat dwi pada telefon mudah alih Huawei? Dengan kebangkitan media sosial, WeChat telah menjadi salah satu alat komunikasi yang sangat diperlukan dalam kehidupan seharian orang ramai. Walau bagaimanapun, ramai orang mungkin menghadapi masalah: log masuk ke beberapa akaun WeChat pada masa yang sama pada telefon mudah alih yang sama. Bagi pengguna telefon mudah alih Huawei, tidak sukar untuk mencapai log masuk WeChat dwi Artikel ini akan memperkenalkan cara mencapai log masuk WeChat dwi pada telefon mudah alih Huawei. Pertama sekali, sistem EMUI yang disertakan dengan telefon mudah alih Huawei menyediakan fungsi yang sangat mudah - pembukaan dua aplikasi. Melalui fungsi pembukaan dwi aplikasi, pengguna boleh serentak

Bahasa pengaturcaraan PHP ialah alat yang berkuasa untuk pembangunan web, yang mampu menyokong pelbagai logik dan algoritma pengaturcaraan yang berbeza. Antaranya, melaksanakan jujukan Fibonacci adalah masalah pengaturcaraan biasa dan klasik. Dalam artikel ini, kami akan memperkenalkan cara menggunakan bahasa pengaturcaraan PHP untuk melaksanakan jujukan Fibonacci, dan melampirkan contoh kod tertentu. Jujukan Fibonacci ialah jujukan matematik yang ditakrifkan seperti berikut: unsur pertama dan kedua bagi jujukan ialah 1, dan bermula dari unsur ketiga, nilai setiap unsur adalah sama dengan jumlah dua unsur sebelumnya. Beberapa elemen pertama urutan

Bagaimana untuk melaksanakan fungsi klon WeChat pada telefon mudah alih Huawei Dengan populariti perisian sosial dan penekanan yang semakin meningkat terhadap privasi dan keselamatan orang ramai, fungsi klon WeChat telah beransur-ansur menjadi tumpuan perhatian. Fungsi klon WeChat boleh membantu pengguna log masuk ke berbilang akaun WeChat pada telefon mudah alih yang sama pada masa yang sama, menjadikannya lebih mudah untuk diurus dan digunakan. Tidak sukar untuk melaksanakan fungsi klon WeChat pada telefon mudah alih Huawei Anda hanya perlu mengikuti langkah berikut. Langkah 1: Pastikan versi sistem telefon mudah alih dan versi WeChat memenuhi keperluan Pertama, pastikan versi sistem telefon mudah alih Huawei anda telah dikemas kini kepada versi terkini, serta Apl WeChat.

Dalam bidang pembangunan perisian hari ini, Golang (bahasa Go), sebagai bahasa pengaturcaraan yang cekap, ringkas dan sangat bersesuaian, semakin digemari oleh pembangun. Perpustakaan standardnya yang kaya dan ciri-ciri konkurensi yang cekap menjadikannya pilihan berprofil tinggi dalam bidang pembangunan permainan. Artikel ini akan meneroka cara menggunakan Golang untuk pembangunan permainan dan menunjukkan kemungkinan besarnya melalui contoh kod tertentu. 1. Kelebihan Golang dalam pembangunan permainan Sebagai bahasa yang ditaip secara statik, Golang digunakan dalam membina sistem permainan berskala besar.

Panduan Pelaksanaan Keperluan Permainan PHP Dengan populariti dan perkembangan Internet, pasaran permainan web menjadi semakin popular. Ramai pembangun berharap untuk menggunakan bahasa PHP untuk membangunkan permainan web mereka sendiri, dan melaksanakan keperluan permainan adalah langkah utama. Artikel ini akan memperkenalkan cara menggunakan bahasa PHP untuk melaksanakan keperluan permainan biasa dan menyediakan contoh kod khusus. 1. Cipta watak permainan Dalam permainan web, watak permainan adalah elemen yang sangat penting. Kita perlu mentakrifkan atribut watak permainan, seperti nama, tahap, nilai pengalaman, dll., dan menyediakan kaedah untuk mengendalikannya

Melaksanakan operasi pembahagian yang tepat di Golang adalah keperluan biasa, terutamanya dalam senario yang melibatkan pengiraan kewangan atau senario lain yang memerlukan pengiraan ketepatan tinggi. Operator bahagian terbina dalam Golang "/" dikira untuk nombor titik terapung, dan kadangkala terdapat masalah kehilangan ketepatan. Untuk menyelesaikan masalah ini, kami boleh menggunakan perpustakaan pihak ketiga atau fungsi tersuai untuk melaksanakan operasi pembahagian yang tepat. Pendekatan biasa ialah menggunakan jenis Tikus daripada pakej matematik/besar, yang menyediakan perwakilan pecahan dan boleh digunakan untuk melaksanakan operasi pembahagian yang tepat.

Tajuk: Penjelasan terperinci tentang fungsi eksport data menggunakan Golang Dengan peningkatan pemformatan, banyak perusahaan dan organisasi perlu mengeksport data yang disimpan dalam pangkalan data ke dalam format yang berbeza untuk analisis data, penjanaan laporan dan tujuan lain. Artikel ini akan memperkenalkan cara menggunakan bahasa pengaturcaraan Golang untuk melaksanakan fungsi eksport data, termasuk langkah terperinci untuk menyambung ke pangkalan data, data pertanyaan dan eksport data ke fail serta menyediakan contoh kod khusus. Untuk menyambung ke pangkalan data terlebih dahulu, kita perlu menggunakan pemacu pangkalan data yang disediakan di Golang, seperti da

Saya benar-benar minta maaf kerana saya tidak dapat memberikan panduan pengaturcaraan masa nyata, tetapi saya boleh memberikan anda contoh kod untuk memberi anda pemahaman yang lebih baik tentang cara menggunakan PHP untuk melaksanakan SaaS. Berikut ialah artikel dalam 1,500 perkataan, bertajuk "Menggunakan PHP untuk melaksanakan SaaS: Analisis komprehensif." Dalam era maklumat hari ini, SaaS (Perisian sebagai Perkhidmatan) telah menjadi cara arus perdana bagi perusahaan dan individu untuk menggunakan perisian. Ia menyediakan cara yang lebih fleksibel dan mudah untuk mengakses perisian. Dengan SaaS, pengguna tidak perlu berada di premis
