一句話:突飛猛進。
工作量大,新技術不斷出現。部門人口暴增三倍。
所以就沒有多少時間寫文章了。
一邊工作,一邊找人。只是,人難找。
找嵌入式系統的人,都是做手機,不想來碰硬體。
找單晶片的人,不懂RTOS。
找馬達控制的人,幾乎沒有工作經驗。
找影像處理的人,不幸的目前無空缺。
有合的真的不多。
2012年8月12日 星期日
簡單多工3.1版
Bee用第3版發展到程式大了,使用的Task數目一多,整個反應時間就慢了。
但有不少Task其實作用時間很短,且工作量很低。
所以就加入了暫時性的工作。
其實考量了可以使用暫時性工作可以用,大部分都是暫時性工作的使用機會高。
這樣就不會一下子增加太多的工作數目,可以保持掃描率,反應不會太慢。
只是暫時性工作要除錯完成再改為暫時性管理方式。因為TaskID一直變的話是不好追蹤的。
新增程式功能說明:
#define MIN_FREE_NUM 3
設定從那一個ID數往後找
unsigned char Get_Temp_Task(void (*p_func)(void));
設定暫時性工作,傳入啟動函式,回傳可用的TaskID。
若回傳為0xFF,則是無空的Task可用。
void Task_Retire(void);
暫時性工作結束
unsigned char Check_Task_Free(unsigned char TaskID);
看工作是否為空閒,主要是用來檢查暫時性工作是否結束。
整體程式:
#include "mt.h"
#define TASK_NUM 4
#define MIN_FREE_NUM 3
extern void SimInit(void);
extern void OS_ENTER_CRITICAL(void);
extern void OS_EXIT_CRITICAL(void);
#define INIT_DEVICE() SimInit()
#define DIS_INTR() OS_ENTER_CRITICAL()
#define ENA_INTR() OS_EXIT_CRITICAL()
// O.S function declaim
void Dummy(void);
unsigned char FuncID;
volatile unsigned char Task_State[TASK_NUM];
unsigned short Task_Delay_Count[TASK_NUM];
void (*TaskFunc[TASK_NUM])(void);
// O.S functions
void InitSystem(void)
{
extern void Task1(void);
extern void Task2(void);
extern void Task3(void);
unsigned char i;
FuncID = 0;
for ( i= 0; i< TASK_NUM ; i++)
{
Task_State[i] = TASK_RUNNING;
Task_Delay_Count[i] = 0;
TaskFunc[i] = Dummy;
}
TaskFunc[0] = Task1;
TaskFunc[1] = Task2;
TaskFunc[2] = Task3;
}
void Sleep_Next(void (*p_func)(void))
{
TaskFunc[FuncID] = p_func;
Task_State[FuncID] = TASK_WAIT;
}
void WakeUp(unsigned char n)
{
Task_State[n] = TASK_RUNNING;
}
void Task_Set_Next(void (*p_func)(void))
{
TaskFunc[FuncID]=p_func;
}
void Dummy(void)
{
Sleep_Next(Dummy);
}
void Task_Delay_Ms_Next(unsigned int n, void (*p_func)(void))
{
if (! n ) n = 1;
TaskFunc[FuncID] = p_func;
Task_Delay_Count[FuncID] = n;
Task_State[FuncID] = TASK_DELAY;
}
void Task_Set_Skip_Next(unsigned int n, void (*p_func)(void))
{
if (! n ) n = 1;
TaskFunc[FuncID] = p_func;
Task_Delay_Count[FuncID] = n;
Task_State[FuncID] = TASK_SKIP;
}
unsigned char Get_Temp_Task(void (*p_func)(void))
{
int i = MIN_FREE_NUM;
while(i < TASK_NUM )
{
if( TaskFunc[i] == Dummy )
{
TaskFunc[i] = p_func;
return i;
}
i++;
}
return 0xff;
}
void Task_Retire(void)
{
Sleep_Next(Dummy);
}
unsigned char Check_Task_Free(unsigned char TaskID)
{
return ( TaskFunc[TaskID] == Dummy )? 1: 0;
}
// O.S functions end
// main loop
void main(void)
{
INIT_DEVICE();
InitSystem();
while (1)
{
switch (Task_State[FuncID])
{
case TASK_RUNNING :
TaskFunc[FuncID]();
break;
case TASK_SKIP :
if ( Task_Delay_Count[FuncID] )
{
Task_Delay_Count[FuncID]--;
if (! Task_Delay_Count[FuncID]) WakeUp(FuncID);
}
break;
default:
break;
}
if ( ++FuncID >= TASK_NUM ) FuncID = 0;
}
}
void TimeTick(void) // This is timer interrupt
{
unsigned char i;
for ( i=0; i< TASK_NUM; i++)
{
if ( Task_State[i] == TASK_DELAY )
{
if ( Task_Delay_Count[i] )
{
Task_Delay_Count[i]--;
if (! Task_Delay_Count[i]) WakeUp(i);
}
}
}
}
開頭檔內容:
void Sleep_Next(void (*p_func)(void));
void WakeUp(unsigned char n);
void Task_Set_Next(void (*p_func)(void));
void Task_Delay_Ms_Next(unsigned int n, void (*p_func)(void));
void Task_Set_Skip_Next(unsigned int n, void (*p_func)(void));
unsigned char Get_Temp_Task(void (*p_func)(void));
void Task_Retire(void);
unsigned char Check_Task_Free(unsigned char TaskID);
// Task State
#define TASK_RUNNING 0
#define TASK_SKIP 1
#define TASK_DELAY 2
#define TASK_WAIT 3
// O.S. Macro
#define SET_TASK(id,p_func) {TaskFunc[id]=p_func;}
#define SET_STATE(id,state) {Task_State[id]=state;}
#define SET_DELAY(id,n) {Task_Delay_Count[id]=n;}
// Time Constant
#define SKIP_CYCLE_TIME_US (0.083)
#define SKIP_US(x) ((int)((x)*(1.0/SKIP_CYCLE_TIME_US)))
測試程式:
#include < stdio.h >
#include "mt.h"
unsigned char temp_count;
void TempTask(void)
{
printf("T");
temp_count++;
if(temp_count < 10)
{
Task_Set_Skip_Next(SKIP_US(500),TempTask);
}
else
{
Task_Retire();
}
}
void Task1(void)
{
unsigned char task_handle;
printf("G");
temp_count = 0;
task_handle = Get_Temp_Task(TempTask);
WakeUp(task_handle);
Task_Delay_Ms_Next(10,Task1);
}
void Task2(void)
{
printf("z");
Task_Delay_Ms_Next(1,Task2);
}
void Task3(void)
{
printf(".");
Task_Set_Skip_Next(SKIP_US(1000),Task3);
}
測試結果:
2012年8月5日 星期日
Cortex-M3 : 遇到HardFault該如何處理
寫Config週邊時最常遇到的是,週邊不動,不然就是HardFault。
若是發展中的程式,還知道現在正在加入的是那一個功能。
但拿到的是舊程式,出現HardFault就糟了,因為從那裏產生的都不知。
其實沒有如此糟,只要去看堆疊內容就行了。
SP+24的位置,就是產生HardFault的位址,一般會是標準函式庫。
就可以查出是那一個呼叫弄錯了。
另外SP+20則是Link Register的內容,可以進一步告知前一個呼叫函式位置。
往前追就可以看到是那一個應用程式弄錯了。
不過大概要會組合語言的人才會知道怎麼回事,原理不多說了。
若是發展中的程式,還知道現在正在加入的是那一個功能。
但拿到的是舊程式,出現HardFault就糟了,因為從那裏產生的都不知。
其實沒有如此糟,只要去看堆疊內容就行了。
SP+24的位置,就是產生HardFault的位址,一般會是標準函式庫。
就可以查出是那一個呼叫弄錯了。
另外SP+20則是Link Register的內容,可以進一步告知前一個呼叫函式位置。
往前追就可以看到是那一個應用程式弄錯了。
不過大概要會組合語言的人才會知道怎麼回事,原理不多說了。
訂閱:
文章 (Atom)