258 lines
4.7 KiB
C
258 lines
4.7 KiB
C
|
// Copyright 2020-2021 Beken
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
#include "rtos_ext.h"
|
||
|
|
||
|
#define port_enter_critical rtos_enter_critical
|
||
|
#define port_exit_critical rtos_exit_critical
|
||
|
|
||
|
bk_err_t rtos_init_event_ex(rtos_event_ext_t * event)
|
||
|
{
|
||
|
if(event->event_semaphore != NULL)
|
||
|
return BK_OK;
|
||
|
|
||
|
event->event_flag = 0;
|
||
|
|
||
|
bk_err_t result = rtos_init_semaphore(&event->event_semaphore, 1);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/* this API may be called from ISR. */
|
||
|
bk_err_t rtos_set_event_ex(rtos_event_ext_t * event, u32 event_flag)
|
||
|
{
|
||
|
u32 int_mask;
|
||
|
|
||
|
if(event->event_semaphore == NULL)
|
||
|
return BK_ERR_NOT_INIT;
|
||
|
|
||
|
if(event_flag == 0)
|
||
|
return BK_OK;
|
||
|
|
||
|
int_mask = port_enter_critical();
|
||
|
|
||
|
event->event_flag |= event_flag;
|
||
|
|
||
|
port_exit_critical(int_mask);
|
||
|
|
||
|
rtos_set_semaphore(&event->event_semaphore);
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
/* support only one task to wait on the event. */
|
||
|
u32 rtos_wait_event_ex(rtos_event_ext_t * event, u32 event_flag, u32 any_event, u32 timeout)
|
||
|
{
|
||
|
if(event->event_semaphore == NULL)
|
||
|
return 0;
|
||
|
|
||
|
if(event_flag == 0)
|
||
|
return 0;
|
||
|
|
||
|
u32 int_mask;
|
||
|
u32 ret_flag;
|
||
|
|
||
|
u32 start_time = rtos_get_time();
|
||
|
u32 cur_time;
|
||
|
u32 elapsed_time = 0;
|
||
|
|
||
|
bk_err_t result;
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
int_mask = port_enter_critical();
|
||
|
|
||
|
ret_flag = (event->event_flag) & event_flag;
|
||
|
|
||
|
if(!any_event) // all events required.
|
||
|
{
|
||
|
if(ret_flag != event_flag)
|
||
|
{
|
||
|
ret_flag = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
event->event_flag ^= ret_flag; // clear read events.
|
||
|
|
||
|
port_exit_critical(int_mask);
|
||
|
|
||
|
if(ret_flag != 0)
|
||
|
{
|
||
|
return ret_flag;
|
||
|
}
|
||
|
|
||
|
if(timeout != BEKEN_WAIT_FOREVER)
|
||
|
{
|
||
|
cur_time = rtos_get_time();
|
||
|
if(cur_time < start_time)
|
||
|
{
|
||
|
elapsed_time = (~cur_time) + 1 + start_time;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
elapsed_time = cur_time - start_time;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
elapsed_time = 0;
|
||
|
}
|
||
|
|
||
|
if(elapsed_time >= timeout)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = rtos_get_semaphore(&event->event_semaphore, timeout - elapsed_time);
|
||
|
|
||
|
if(result != BK_OK)
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
bk_err_t rtos_deinit_event_ex(rtos_event_ext_t * event)
|
||
|
{
|
||
|
if(event->event_semaphore == NULL)
|
||
|
return BK_OK;
|
||
|
|
||
|
bk_err_t result = rtos_deinit_semaphore(&event->event_semaphore);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
#define RTOS_HISR_MAX 32
|
||
|
|
||
|
static beken_semaphore_t hisr_notify_sema;
|
||
|
static u8 hisr_event_grp[(RTOS_HISR_MAX + 7) / 8]; // 64 interrupts.
|
||
|
static rtos_hisr_cb_t *hisr_list[RTOS_HISR_MAX];
|
||
|
static u8 cur_hisr_id; // for debug.
|
||
|
|
||
|
static u8 get_hisr_event_id(void)
|
||
|
{
|
||
|
u8 event_id = 0xFF;
|
||
|
u8 i, j;
|
||
|
u32 int_mask;
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
event_id = 0xFF;
|
||
|
|
||
|
int_mask = port_enter_critical();
|
||
|
|
||
|
for(i = 0; i < ARRAY_SIZE(hisr_event_grp); i++)
|
||
|
{
|
||
|
if(hisr_event_grp[i] != 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(i < ARRAY_SIZE(hisr_event_grp))
|
||
|
{
|
||
|
for(j = 0; j < 8; j++)
|
||
|
{
|
||
|
if(hisr_event_grp[i] & (0x01 << j))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hisr_event_grp[i] &= ~(0x01 << j);
|
||
|
|
||
|
event_id = (i << 3) + j;
|
||
|
}
|
||
|
|
||
|
port_exit_critical(int_mask);
|
||
|
|
||
|
if(event_id < RTOS_HISR_MAX)
|
||
|
return event_id;
|
||
|
|
||
|
rtos_get_semaphore(&hisr_notify_sema, BEKEN_WAIT_FOREVER);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//void rtos_hisr_handler( void *param )
|
||
|
void rtos_hisr_task( void *param )
|
||
|
{
|
||
|
u8 evt_id;
|
||
|
|
||
|
// task init
|
||
|
rtos_init_semaphore(&hisr_notify_sema, 1);
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
evt_id = get_hisr_event_id();
|
||
|
|
||
|
cur_hisr_id = hisr_list[evt_id]->hisr_id;
|
||
|
|
||
|
hisr_list[evt_id]->hisr(hisr_list[evt_id]->hisr_param);
|
||
|
|
||
|
cur_hisr_id = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bk_err_t rtos_activate_hisr(rtos_hisr_cb_t *hisr_cb)
|
||
|
{
|
||
|
if(hisr_cb->inited == 0)
|
||
|
{
|
||
|
return BK_FAIL;
|
||
|
}
|
||
|
|
||
|
if(hisr_cb->event_id >= RTOS_HISR_MAX)
|
||
|
{
|
||
|
return BK_FAIL;
|
||
|
}
|
||
|
|
||
|
u32 int_mask = port_enter_critical();
|
||
|
hisr_event_grp[hisr_cb->event_id >> 3] |= 0x01 << (hisr_cb->event_id & 7);
|
||
|
port_exit_critical(int_mask);
|
||
|
|
||
|
rtos_set_semaphore(&hisr_notify_sema);
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|
||
|
bk_err_t rtos_create_hisr(rtos_hisr_cb_t *hisr_cb, high_isr_t hisr, void *param, u32 hisr_id)
|
||
|
{
|
||
|
u8 i;
|
||
|
|
||
|
for(i = 0; i < RTOS_HISR_MAX; i++)
|
||
|
{
|
||
|
if(hisr_list[i] == NULL)
|
||
|
break;
|
||
|
else
|
||
|
{
|
||
|
if((hisr_list[i]->hisr == hisr) && (hisr_list[i]->hisr_param == param))
|
||
|
return BK_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(i >= RTOS_HISR_MAX)
|
||
|
return BK_FAIL;
|
||
|
|
||
|
hisr_cb->hisr = hisr;
|
||
|
hisr_cb->hisr_param = param;
|
||
|
hisr_cb->hisr_id = hisr_id;
|
||
|
hisr_cb->event_id = i;
|
||
|
hisr_cb->inited = 1;
|
||
|
|
||
|
hisr_list[hisr_cb->event_id] = hisr_cb;
|
||
|
|
||
|
return BK_OK;
|
||
|
}
|
||
|
|