📄 djyos.c
字号:
pg_event_running->event_status.bit.evtt_done_sync = 0;
int_restore_asyn_signal();
return cn_sync_timeout;
}else
{
int_restore_asyn_signal();
return cn_sync_success;
}
}
//----事件类型弹出同步---------------------------------------------------------
//功能: 把正在运行的事件加入到指定事件类型的弹出同步队列中去,然后重新调度。弹出
// 同步是指以该事件类型的事件弹出若干次为同步条件。
//参数: evtt_id,目标事件类型号
// pop_times,弹出次数,不能是0.
// timeout,超时设置,单位是毫秒,cn_timeout_forever=无限等待,0则立即按
// 超时返回。非0值将被向上调整为cn_tick_ms的整数倍
//返回: cn_sync_success=同步条件成立返回,
// cn_sync_timeout=超时返回,
// cn_sync_error=出错,
// 本函数必须联系共享文档的相关章节才容易读懂,注释难于解释那么清楚的。
//----------------------------------------------------------------------------
uint32_t y_evtt_pop_sync(uint16_t evtt_id,uint16_t pop_times,uint32_t timeout)
{
struct event_type *evtt;
struct event_script *pl_ecb;
evtt = &tg_evtt_table[evtt_id];
//不能在禁止调度的情况下执行同步操作,弹出次数不能设为0
if((y_query_sch() == false) || (pop_times == 0))
return cn_sync_error;
if(timeout == 0)
return cn_sync_timeout;
int_save_asyn_signal();
if(evtt->property.registered == false)
{//该事件类型是无效事件类型
int_restore_asyn_signal();
return cn_sync_error;
}
__y_cut_ready_event(pg_event_running);
pg_event_running->next = NULL;
pg_event_running->previous = NULL;
pg_event_running->sync_counter = pop_times;
//以下把pg_event_running加入到目标事件的同步队列中
pg_event_running->sync_head = &evtt->pop_sync;
if(evtt->pop_sync != NULL)
{//被同步事件的同步队列不是空的
pl_ecb = evtt->pop_sync;
do
{//本循环找到第一个剩余弹出次数不小于新事件的事件.
if(pl_ecb->sync_counter < pop_times)
pl_ecb = pl_ecb->multi_next;
else
break;
}while(pl_ecb != evtt->pop_sync);
//下面把新事件(pg_event_running)插入到队列中
pg_event_running->multi_next = pl_ecb;
pg_event_running->multi_previous = pl_ecb->multi_previous;
pl_ecb->multi_previous->multi_next = pg_event_running;
pl_ecb->multi_previous = pg_event_running;
if(evtt->pop_sync->sync_counter > pop_times)
evtt->pop_sync = pg_event_running;
}else
{//被同步事件的同步队列是空的
evtt->pop_sync = pg_event_running;
pg_event_running->multi_next = pg_event_running;
pg_event_running->multi_previous = pg_event_running;
}
pg_event_running->last_status.all = pg_event_running->event_status.all;
pg_event_running->event_status.bit.evtt_pop_sync = 1;
if(timeout != cn_timeout_forever)
{
pg_event_running->event_status.bit.wait_overtime = 1;
__y_addto_delay((timeout + cn_tick_ms -1)/cn_tick_ms);
}
int_restore_asyn_signal(); //恢复中断会引发重新调度
int_save_asyn_signal();
//检查从哪里返回,是超时还是同步事件完成。
if(pg_event_running->event_status.bit.evtt_pop_sync)
{//说明同步条件未到,从超时返回,应从目标事件的同步队列中取出事件。
//此时,同步条件肯定还没有达成。
pg_event_running->event_status.bit.evtt_pop_sync = 0;
int_restore_asyn_signal();
return cn_sync_timeout;
}else
{
int_restore_asyn_signal();
return cn_sync_success;
}
}
//----报告事件------------------------------------------------------------------
//功能:向操作系统报告发生事件,操作系统接报后,将分配或建立合适的线程处理事件.
//参数:event_type,发生的事件类型
// parameter0,parameter1,事件参数
// prio,事件优先级,0表示使用默认值(存在事件类型表pg_event_type_table中)
//返回:若不能获取事件控制块,返回-1,否则返回事件id。
//注: 不会因不能获得事件控制块而阻塞。
//------------------------------------------------------------------------------
uint16_t y_event_pop( uint16_t evtt_id,
uint32_t parameter0,
uint32_t parameter1,
ufast_t prio)
{
struct event_script *pl_ecb;
struct event_type *pl_evtt;
uint16_t result;
ufast_t my_prio;
if(evtt_id >= cn_evtts_limit)
return cn_invalid_event_id;
pl_evtt =&tg_evtt_table[evtt_id];
if((pl_evtt->property.registered == 0) //类型未登记
|| (prio >= cn_prio_sys_service)) //不能pop休眠事件
{
y_error_login(enum_knl_etcb_error,NULL);
return cn_invalid_event_id;
}
int_save_asyn_signal(); //关异步信号(关调度)
pl_evtt->pop_sum++;
//下面处理弹出同步队列,必须联系共享文档的相关章节才容易读懂,注释难于解释
//那么清楚的。
while(pl_evtt->pop_sync != NULL)
{
pl_ecb = pl_evtt->pop_sync;
if(pl_ecb->sync_counter == 1)
{
pl_ecb->last_status.all = pl_ecb->event_status.all;
pl_ecb->event_status.bit.evtt_pop_sync = 0;
if(pl_ecb->event_status.bit.wait_overtime) //指定的超时未到
{
__y_resume_delay(pl_ecb); //从闹钟队列中移除事件
pl_ecb->event_status.bit.wait_overtime = 0;
}
if(pl_ecb->multi_next == pl_ecb->multi_previous)
{//是最后一个事件
pl_evtt->pop_sync = NULL;
}else
{
pl_evtt->pop_sync = pl_ecb->multi_next;
pl_ecb->multi_next->multi_previous = pl_ecb->multi_next;
pl_ecb->multi_previous->multi_next = pl_ecb->multi_previous;
}
__y_event_ready(pl_ecb);
}else
{
pl_ecb->sync_counter--;
}
}
//mark型事件需要正在执行的done才能执行新事件。
//mark型事件在队列中可能的组合为:
// 已clear repeats 处理方式
// 未clear mark_unclear in_use
//1 有 无 NULL ==0 1 新事件由mark_unclear指针指向
//2 有 有 !NULL !=0 1 repeats++,考虑参数替换
//3 无 有 !NULL !=0 1 repeats++,考虑参数替换
//4 无 无 NULL ==0 0 新事件加入就绪队列
if(pl_evtt->mark_unclear != NULL)
{// mark型事件的第2和第3种情况
pl_ecb = pl_evtt->mark_unclear; //取事件控制块
if(pl_evtt->property.overlay == 1) //参数替换型,替换参数
{
pl_ecb->parameter0 = parameter0;
pl_ecb->parameter1 = parameter1;
}
if(pl_evtt->repeats != cn_limit_uint16)
pl_evtt->repeats++; //事件发生次数增量
result = pl_ecb->event_id;
goto end_pop; //注意 goto
}
if(prio != 0)
my_prio = prio; //设置事件优先级,
else
my_prio = pl_evtt->default_prio; //从事件类型中继承优先级
//以下处理非mark型事件或者mark型事件的第1、4种情况
if(pg_event_free==NULL) //没有空闲的事件控制块
{
y_error_login(enum_knl_no_free_ecb,NULL);
result = cn_invalid_event_id;
}else if((pl_evtt->property.mark == false)
&& (pl_evtt->repeats >= pl_evtt->vpus_limit))
{
y_error_login(enum_knl_vpu_over,NULL);
result = cn_invalid_event_id;
}else //有空闲事件控制块
{
pl_ecb = pg_event_free; //从空闲链表中提取一个事件控制块
pg_event_free=pg_event_free->next; //空闲事件控制块数量减1
if(pl_evtt->repeats != cn_limit_uint16)
pl_evtt->repeats++; //repeats增量
//设置新事件的参数
pl_ecb->next = NULL;
pl_ecb->previous = NULL;
pl_ecb->multi_next = NULL;
pl_ecb->multi_previous = NULL;
pl_ecb->vm = NULL;
pl_ecb->sync = NULL;
pl_ecb->sync_head = NULL;
pl_ecb->start_time=y_get_time(); //事件发生时间
pl_ecb->consumed_time = 0;
pl_ecb->delay_start = 0;
pl_ecb->delay_end = 0;
pl_ecb->error_no = 0;
pl_ecb->parameter0=parameter0; //设置事件参数
pl_ecb->parameter1=parameter1; //设置事件参数
pl_ecb->wait_mem_size = 0;
pl_ecb->last_status.all = 0;
pl_ecb->event_status.all = 0;
pl_ecb->prio = my_prio;
pl_ecb->evtt_id=evtt_id; //设置事件类型
pl_ecb->repeats = 0;
pl_ecb->held_device = NULL;
pl_ecb->local_memory = 0;
if(pl_evtt->property.mark == true) //这是mark型事件
{
pl_evtt->mark_unclear = pl_ecb;
if(pl_evtt->property.in_use == 1) //第1种情况
{
}else //第4种情况
{
__y_event_ready(pl_ecb);
}
}else //非mark型事件
__y_event_ready(pl_ecb);
pl_evtt->property.in_use = 1;
result = pl_ecb->event_id;
}
end_pop:
int_restore_asyn_signal(); //恢复中断状态
return result;
}
//----初始化tick---------------------------------------------------------------
//功能: 初始化定时器,并连接tick中断函数,启动定时器.
//参数: 无
//返回: 无
//备注: 本函数是移植关键函数.
//-----------------------------------------------------------------------------
void __y_init_tick(void)
{
//连接timer5作为tick中断
int_isr_connect(cn_irq_line_timer5,__y_isr_tick);
int_setto_asyn_signal(cn_irq_line_timer5); //tick中断被设为异步信号
//以下设置定时器参数,需与port_config.h中cn_tick_ms、cn_tick_hz和
//cn_fine_us、cn_fine_hz的定义一致
timer_set_clk_source(5,0); //主频的1/2分频
timer_set_precale(2,7); //预分频数:32分频
//以上把定时器输入时钟的频率设为1M,与常数cn_fine_hz对应
timer_set_counter(5,(uint16_t)(cn_tick_ms*cn_timer_clk/16000));
timer_set_type(5,1); //设置tick定时器连续工作
timer_reload(5); //重载定时值
timer_start(5); //启动定时器
int_restore_line(cn_irq_line_timer5);//启动tick中断
}
//----启动操作系统--------------------------------------------------------------
//功能: 初始化时钟嘀嗒,复位异步信号使能状态,选出最高优先级事件,调用
// __asm_turnto_context把上下文切换到这个事件
//参数: 无
//返回: 无
//_____________________________________________________________________________
void __y_start_os(void)
{
__y_init_tick();
//本句为容错性质,以防用户模块初始化过程中没有成对调用异步信号使能与禁止函数
__int_reset_asyn_signal();
__y_select_event_to_run();
pg_event_running = pg_event_ready;
__asm_turnto_context(pg_event_running->vm);
}
//----完成事件------------------------------------------------------------------
//功能:向操作系统报告事件已经完成,操作系统接到报告后,完成清理工作.
// 1.如果事件同步队列非空,把同步事件放到ready表。
// 2.如果持有设
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -