276 lines
6.8 KiB
C
276 lines
6.8 KiB
C
#include "asm/power_interface.h"
|
||
#include "clock.h"
|
||
#include "os/os_api.h"
|
||
|
||
#define MSG_ENTER_CRITICAL() lp_lock()
|
||
#define MSG_EXIT_CRITICAL() lp_unlock()
|
||
|
||
#define P11_WKUP_MSYS(msg) P11_SYSTEM->P2M_INT_SET = BIT(P2M_APP_INDEX)
|
||
#define MSYS_WKUP_P11(msg) P11_SYSTEM->M2P_INT_SET = BIT(M2P_APP_INDEX)
|
||
|
||
static bool post_ack_flag = 1;
|
||
|
||
/*
|
||
function: 从缓存buf读取指定长度数据
|
||
return val: -2,没有数据 -1,数据不足:0,读取到数据
|
||
param len: 读取数据长度
|
||
*/
|
||
static int lp_buf_read(LP_Q *q, void *buf, u32 len)
|
||
{
|
||
if (q->count == 0) {
|
||
return LP_BUF_READ_NO_DATA;
|
||
}
|
||
|
||
if (q->count < len) {
|
||
return LP_BUF_READ_NOT_ENOUGH_DATA;
|
||
}
|
||
|
||
u32 end = (q->out + len) % q->size;
|
||
if (end > q->out) {
|
||
memcpy(buf, (void *)(P11_RAM_BASE + q->start + q->out), len);
|
||
} else {
|
||
memcpy(buf, (void *)(P11_RAM_BASE + q->start + q->out), q->size - q->out);
|
||
memcpy((void *)((u8 *)buf + (q->size - q->out)), (void *)(P11_RAM_BASE + q->start), end);
|
||
}
|
||
|
||
q->out = end;
|
||
q->count -= len;
|
||
|
||
return LP_BUF_NO_ERR;
|
||
}
|
||
|
||
static int lp_buf_write_enable(LP_Q *q, u32 len)
|
||
{
|
||
if ((q->count + len) > q->size) {
|
||
return LP_BUF_WRITE_OVER;
|
||
} else {
|
||
return LP_BUF_NO_ERR;
|
||
}
|
||
}
|
||
|
||
/*
|
||
function: 从缓存buf写入指定长度数据
|
||
return val: 0,写入成功
|
||
param len: 写入的数据长度
|
||
*/
|
||
static int lp_buf_write(LP_Q *q, const void *buf, u32 len)
|
||
{
|
||
u32 end = (q->in + len) % q->size;
|
||
if (end > q->in) {
|
||
memcpy((void *)(P11_RAM_BASE + q->start + q->in), buf, len);
|
||
} else {
|
||
memcpy((void *)(P11_RAM_BASE + q->start + q->in), buf, q->size - q->in);
|
||
memcpy((void *)(P11_RAM_BASE + q->start), (u8 *)buf + (q->size - q->in), end);
|
||
}
|
||
|
||
q->in = end;
|
||
q->count += len;
|
||
|
||
return LP_BUF_NO_ERR;
|
||
}
|
||
|
||
/*
|
||
* 接收到ack消息处理过程中调用
|
||
*/
|
||
void config_post_ack_flag(u32 enable)
|
||
{
|
||
local_irq_disable();
|
||
if (enable) {
|
||
post_ack_flag = 1;
|
||
} else {
|
||
post_ack_flag = 0;
|
||
}
|
||
local_irq_enable();
|
||
}
|
||
|
||
static u32 m2p_get_ack_flag(u32 index)
|
||
{
|
||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF_ADDR0 | P2M_CBUF_ADDR1 << 8 | P2M_CBUF_ADDR2 << 16 | P2M_CBUF_ADDR3 << 24));
|
||
|
||
MSG_ENTER_CRITICAL();
|
||
u32 ret = msg_q_p->ack_flag & BIT(index);
|
||
MSG_EXIT_CRITICAL();
|
||
|
||
return ret ? 0 : 1;
|
||
}
|
||
|
||
u32 msys_ack_p11(u32 index)
|
||
{
|
||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF1_ADDR0 | P2M_CBUF1_ADDR1 << 8 | P2M_CBUF1_ADDR2 << 16 | P2M_CBUF1_ADDR3 << 24));
|
||
|
||
MSG_ENTER_CRITICAL();
|
||
msg_q_p->ack_flag &= ~BIT(index);
|
||
MSG_EXIT_CRITICAL();
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* function:主系统向P11发送消息,往消息池丢数据
|
||
*
|
||
* param type: 消息类型,P11收到消息后根据消息类型匹配回调函数
|
||
* param ack:P11收到消息执行完成后是否发送应答消息给主系统,此时主系统死等消息
|
||
* 并处理P11发送过来的所有消息
|
||
* param len:发送消息的长度,单位为一个字节
|
||
* param msg:发送的消息
|
||
*
|
||
*/
|
||
int m2p_post_msg(u32 type, u32 ack, const void *msg, u32 len)
|
||
{
|
||
struct lp_msg_head head;
|
||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF_ADDR0 | P2M_CBUF_ADDR1 << 8 | P2M_CBUF_ADDR2 << 16 | P2M_CBUF_ADDR3 << 24));
|
||
|
||
if (ack == 1) {
|
||
ASSERT(!(cpu_in_irq() || cpu_irq_disabled()), "m2p_post_msg ack");
|
||
}
|
||
|
||
//关中断,接口互斥
|
||
local_irq_disable();
|
||
MSG_ENTER_CRITICAL();
|
||
|
||
u32 index = 0;
|
||
if (ack) {
|
||
msg_q_p->ack_flag |= BIT(index);
|
||
/*收到ACK消息处理函数,不允许发送ACK消息*/
|
||
if ((post_ack_flag != 1) && (!strcmp(os_current_task(), "pmu_task"))) {
|
||
ASSERT(0, "post_ack_flag check fail!");
|
||
}
|
||
}
|
||
|
||
head.type = type;
|
||
head.ack = ack;
|
||
head.len = len;
|
||
head.index = index;
|
||
|
||
if (lp_buf_write_enable(msg_q_p, len + sizeof(struct lp_msg_head)) == -1) {
|
||
goto __err;
|
||
/* return MSG_BUF_WRITE_OVER; */
|
||
}
|
||
|
||
//写头
|
||
lp_buf_write(msg_q_p, &head, sizeof(struct lp_msg_head));
|
||
|
||
//写数据
|
||
lp_buf_write(msg_q_p, msg, len);
|
||
|
||
MSYS_WKUP_P11();
|
||
|
||
MSG_EXIT_CRITICAL();
|
||
|
||
if (ack) {
|
||
while (1) {
|
||
if (m2p_get_ack_flag(index)) {
|
||
break;
|
||
}
|
||
//需要延时100us,否则p11开打印后会收不到消息导致卡死
|
||
udelay(100);
|
||
//P11等待ACK同时处理消息,防止死锁
|
||
//p2m_msg_hdl();
|
||
}
|
||
}
|
||
|
||
|
||
local_irq_enable();
|
||
return MSG_NO_ERROR;
|
||
__err:
|
||
MSG_EXIT_CRITICAL();
|
||
local_irq_enable();
|
||
return MSG_BUF_WRITE_OVER;
|
||
}
|
||
|
||
/*
|
||
* function:从消息池中获取P11发送过来的消息
|
||
* param head:消息的头部,包含消息类型、长度等信息
|
||
* param len:读取消息内存的长度
|
||
* param msg:读取到消息
|
||
*
|
||
* return val: MSG_NO_MSG
|
||
* MSG_NO_ERROR
|
||
* MSG_BUF_ERROR
|
||
* MSG_BUF_READ_OVER
|
||
*
|
||
*/
|
||
int p2m_get_msg(struct lp_msg_head *head, void *msg, u32 len)
|
||
{
|
||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF1_ADDR0 | P2M_CBUF1_ADDR1 << 8 | P2M_CBUF1_ADDR2 << 16 | P2M_CBUF1_ADDR3 << 24));
|
||
|
||
//长度至少是头+1byte数据
|
||
if (len < sizeof(struct lp_msg_head) + 1) {
|
||
return MSG_BUF_READ_OVER;
|
||
}
|
||
|
||
local_irq_disable();
|
||
MSG_ENTER_CRITICAL();
|
||
|
||
//先读取头部数据
|
||
int ret = lp_buf_read(msg_q_p, head, sizeof(struct lp_msg_head));
|
||
if (ret == LP_BUF_READ_NO_DATA) {
|
||
//若没有数据则进入低功耗
|
||
MSG_EXIT_CRITICAL();
|
||
|
||
//确保每次事件都能唤醒p11
|
||
//get no msg,cpu enter lowpower
|
||
//p11_lowpower_schedule();
|
||
|
||
local_irq_enable();
|
||
|
||
return MSG_NO_MSG;
|
||
|
||
} else if (ret == LP_BUF_READ_NOT_ENOUGH_DATA) {
|
||
MSG_EXIT_CRITICAL();
|
||
local_irq_enable();
|
||
//读取头部的数据长度不够返回错误
|
||
return MSG_BUF_ERROR;
|
||
|
||
} else {
|
||
|
||
//判断长度够不够
|
||
if (len < head->len) {
|
||
MSG_EXIT_CRITICAL();
|
||
local_irq_enable();
|
||
//读了头,数据读不了返回错误
|
||
return MSG_BUF_READ_OVER;
|
||
}
|
||
|
||
ret = lp_buf_read(msg_q_p, msg, head->len);
|
||
if (ret != LP_BUF_NO_ERR) {
|
||
MSG_EXIT_CRITICAL();
|
||
local_irq_enable();
|
||
return MSG_BUF_ERROR;
|
||
}
|
||
|
||
}
|
||
|
||
MSG_EXIT_CRITICAL();
|
||
local_irq_enable();
|
||
|
||
return MSG_NO_ERROR;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* function:主系统向P11发送消息,往消息池丢数据
|
||
*
|
||
* param name: null
|
||
* param argc:参数个数
|
||
*/
|
||
int task_post_msg2p11(char *name, int argc, ...)
|
||
{
|
||
int msg[16];
|
||
va_list argptr;
|
||
va_start(argptr, argc);
|
||
int param;
|
||
ASSERT(argc < sizeof(msg) / sizeof(msg[0]))
|
||
for (int i = 0; i < argc; ++i) {
|
||
param = va_arg(argptr, int);
|
||
msg[i] = param;
|
||
}
|
||
int err = m2p_post_msg(MSG_APP, 0, (u8 *)msg, argc * sizeof(int));
|
||
ASSERT(!err);
|
||
va_end(argptr);
|
||
return 0;
|
||
}
|
||
|
||
|