Files
AC707N/SDK/cpu/power/msg.c
T
2025-12-03 11:12:34 +08:00

276 lines
6.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}