初版
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
#include "includes.h"
|
||||
|
||||
/*
|
||||
1.共享buf互斥操作,注意P11在等待主系统BUF锁时候需要响应主系统的操作,
|
||||
防止主系统等待导致死锁,处理来自主系统的M2P中断(通过硬件lock不需要这一点)
|
||||
|
||||
2.接口互斥,不能同时操作
|
||||
P11在等待主系统ack消息时,也要防止死锁(P11和主系统同时发送ACK消息时会死锁),
|
||||
有以下处理:
|
||||
|
||||
主系统
|
||||
1.主系统不能在关中断/中断中发送ACK类型的消息
|
||||
2.发送ACK类型的消息需要互斥,即不允许同时发多个ACK类型消息
|
||||
3.不允许在收到ACK类型消息处理函数中发送ACK类型消息的嵌套,收到ACK类型消息
|
||||
调用post_ack_flag=0,发送函数判断post_ack_flag=0且当前任务为pmu_task则断言
|
||||
|
||||
P11系统:
|
||||
1.P11系统不能在关中断/中断中发送ACK类型的消息
|
||||
2.不允许在收到ACK类型消息后,又发送ACK类型消息,由于不会在中断中发送ACK类型消息,
|
||||
在收到ACK类型的消息后调用post_ack_flag=0,发送函数内部检查post_ack_flag=0则断言
|
||||
3.不允许重复发送ACK类型的消息,由于一点的保证
|
||||
4.主系统和P11同时发ACK类型的消息,P11需要响应主系统
|
||||
*/
|
||||
|
||||
#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 LP_Q m2p_msg_q;
|
||||
static LP_Q p2m_msg_q;
|
||||
static u8 m2p_pool[MAX_POOL] ALIGNED(4);
|
||||
static u8 p2m_pool[MAX_POOL] ALIGNED(4);
|
||||
static bool post_ack_flag = 1;
|
||||
|
||||
|
||||
/*
|
||||
function: 从缓存buf读取指定长度数据
|
||||
param len: 读取数据长度
|
||||
*/
|
||||
static int lp_buf_read(LP_Q *q, u8 *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(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, u8 *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), buf + (q->size - q->in), end);
|
||||
}
|
||||
|
||||
q->in = end;
|
||||
q->count += len;
|
||||
|
||||
return LP_BUF_NO_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* function:从消息池中获取主系统发送过来的消息
|
||||
* param head:消息的头部,包含消息类型、长度等信息
|
||||
* param len:读取消息内存的长度
|
||||
* param msg:读取到消息
|
||||
*
|
||||
* return val: MSG_NO_MSG
|
||||
* MSG_NO_ERROR
|
||||
* MSG_BUF_ERROR
|
||||
* MSG_BUF_READ_OVER
|
||||
*
|
||||
*/
|
||||
int m2p_get_msg(struct lp_msg_head *head, u8 *msg, u32 len)
|
||||
{
|
||||
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));
|
||||
|
||||
//长度至少是头+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, (u8 *)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发送消息,往消息池丢数据,该函数可实现向P11主循环推数据
|
||||
*
|
||||
* param type: 消息类型,P11收到消息后根据消息类型匹配回调函数
|
||||
* param ack:该函数不需要ack参数,也即发送的头index为0,预留给该函数使用
|
||||
* param len:发送消息的长度,单位为一个字节
|
||||
* param msg:发送的消息
|
||||
*
|
||||
*/
|
||||
int m2p_post_msg(u32 type, u32 ack, u8 *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));
|
||||
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
/*P11的m2p接口不需要ack与index*/
|
||||
head.type = type;
|
||||
head.ack = 0;
|
||||
head.len = len;
|
||||
head.index = 0;
|
||||
|
||||
if (lp_buf_write_enable(msg_q_p, len + sizeof(struct lp_msg_head)) == LP_BUF_WRITE_OVER) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
return MSG_BUF_WRITE_OVER;
|
||||
}
|
||||
|
||||
//写头
|
||||
lp_buf_write(msg_q_p, (u8 *)&head, sizeof(struct lp_msg_head));
|
||||
|
||||
//写数据
|
||||
lp_buf_write(msg_q_p, msg, len);
|
||||
|
||||
MSYS_WKUP_P11();
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
return MSG_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* 接收到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 p2m_get_ack_flag(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();
|
||||
u32 ret = msg_q_p->ack_flag & BIT(index);
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
u32 p11_ack_msys(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();
|
||||
msg_q_p->ack_flag &= ~BIT(index);
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* function:P11向主系统发送消息,往消息池丢数据
|
||||
*
|
||||
* param type: 消息类型,主系统收到消息后根据消息类型匹配回调函数
|
||||
* param ack:P11收到消息执行完成后是否发送应答消息给主系统,P11死等消息
|
||||
* 并处理主系统发送过来的所有消息
|
||||
* param len:发送消息的长度,单位为一个字节
|
||||
* param msg:发送的消息
|
||||
*
|
||||
*/
|
||||
int p2m_post_msg(u32 type, u32 ack, u8 *msg, u32 len)
|
||||
{
|
||||
u32 param;
|
||||
struct lp_msg_head head;
|
||||
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));
|
||||
|
||||
/*不允许在中断函数/关中断发阻塞操作,因为阻塞的同时要处理
|
||||
主系统发的消息,不建议在中断函数处理/关闭中断处理*/
|
||||
if (ack == 1) {
|
||||
ASSERT(!(cpu_in_irq() || cpu_irq_disable()), "p2m_post_msg ack");
|
||||
}
|
||||
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
u32 index = 0;
|
||||
if (ack) {
|
||||
msg_q_p->ack_flag |= BIT(0);
|
||||
/*收到ACK消息处理函数,不允许发送ACK消息*/
|
||||
if (post_ack_flag != 1) {
|
||||
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)) == LP_BUF_WRITE_OVER) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
return MSG_BUF_WRITE_OVER;
|
||||
}
|
||||
|
||||
//写头
|
||||
lp_buf_write(msg_q_p, (u8 *)&head, sizeof(struct lp_msg_head));
|
||||
|
||||
//写数据
|
||||
lp_buf_write(msg_q_p, msg, len);
|
||||
|
||||
__power_recover();
|
||||
|
||||
P11_WKUP_MSYS();
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
if (ack) {
|
||||
while (1) {
|
||||
if (p2m_get_ack_flag(index)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*主系统可能在等待P11的消息,处理来自主系统的消息,防止死锁*/
|
||||
if (m2p_msg_hdl(head.index)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MSG_NO_ERROR;
|
||||
}
|
||||
|
||||
void message_init()
|
||||
{
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
memset((void *)m2p_pool, 0, MAX_POOL);
|
||||
memset((void *)p2m_pool, 0, MAX_POOL);
|
||||
|
||||
//初始化m2p消息队列
|
||||
m2p_msg_q.in = 0;
|
||||
m2p_msg_q.out = 0;
|
||||
m2p_msg_q.start = (u32)m2p_pool;
|
||||
m2p_msg_q.count = 0;
|
||||
m2p_msg_q.size = MAX_POOL;
|
||||
m2p_msg_q.ack_flag = 0;
|
||||
|
||||
//初始化p2m消息队列
|
||||
p2m_msg_q.in = 0;
|
||||
p2m_msg_q.out = 0;
|
||||
p2m_msg_q.start = (u32)p2m_pool;
|
||||
p2m_msg_q.count = 0;
|
||||
p2m_msg_q.size = MAX_POOL;
|
||||
p2m_msg_q.ack_flag = 0;
|
||||
|
||||
//赋值m2p消息队列描述地址
|
||||
u32 addr = (u32)&m2p_msg_q;
|
||||
P2M_CBUF_ADDR0 = (addr) & 0xff;
|
||||
P2M_CBUF_ADDR1 = (addr >> 8) & 0xff;
|
||||
P2M_CBUF_ADDR2 = (addr >> 16) & 0xff;
|
||||
P2M_CBUF_ADDR3 = (addr >> 24) & 0xff;
|
||||
|
||||
//赋值p2m消息队列描述地址
|
||||
addr = (u32)&p2m_msg_q;
|
||||
P2M_CBUF1_ADDR0 = (addr) & 0xff;
|
||||
P2M_CBUF1_ADDR1 = (addr >> 8) & 0xff;
|
||||
P2M_CBUF1_ADDR2 = (addr >> 16) & 0xff;
|
||||
P2M_CBUF1_ADDR3 = (addr >> 24) & 0xff;
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
}
|
||||
Reference in New Issue
Block a user