这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享评测,赢取加热台】多核基于共享内存的虚拟串口打印日志功能实现

共3条 1/1 1 跳转至

【分享评测,赢取加热台】多核基于共享内存的虚拟串口打印日志功能实现

工程师
2024-11-16 11:12:48   被打赏 28 分(兑奖)     打赏

简介:

       现在的mcu 多核已经是很常见的了,对于多核调试时uart log 是一种使用比较常用的方式,对于多核我们可以给每一个核分配一个物理串口,如果资源比较紧张我么也可以和其他核共享一个串口来打印,我们本次的试验是使用后者的方式core0 核 core1 共享一个串口进行打印。

    其实现思路是通过核间通信的share memory,在share memory 中分配一段内存中分配一段空间按照Ring buff 的方式进行存储,一端进行写入另一端读取,然后再CORE0中将数据转发到物理串口,对应的实现原理如下。


image.png

 

代码实现

按照上述share memory 中的数据管理方式本地定义如下数据结构

#define VUART_CORE0_RX_CORE1_TX_BUFFER_SIZE   256
#define VUART_CORE0_TX_CORE1_RX_BUFFER_SIZE   128

//#pragma pack(1)
struct virual_uart
{
    char magic[4];/* VURT */
    RingBuffer core0_rx_core1_tx;
    RingBuffer core0_tx_core1_rx;
    uint8_t core0_rx_core1_tx_buff[VUART_CORE0_RX_CORE1_TX_BUFFER_SIZE];
    uint8_t core0_tx_core1_rx_buff[VUART_CORE0_TX_CORE1_RX_BUFFER_SIZE]; 
};

按照上述流程,在CORE0 侧初始化share memory ,并将share memory 的地址信息通过和间通信的机制通知到CORE1,代码如下。

#ifdef APP_USING_VIRTUAL_UART 
static struct virual_uart virual_uart0 @ "vuart0_sh_mem_section";


static void virual_uart_init(struct virual_uart * p_vuart)
{
    /* init memory buffer */
    memset((void *)p_vuart->core0_rx_core1_tx_buff,0,sizeof(p_vuart->core0_rx_core1_tx_buff));
    memset((void *)p_vuart->core0_tx_core1_rx_buff,0,sizeof(p_vuart->core0_tx_core1_rx_buff));
    
    /* init ringbuffer */
    RingBuffer_Init(&p_vuart->core0_rx_core1_tx,p_vuart->core0_rx_core1_tx_buff,sizeof(p_vuart->core0_rx_core1_tx_buff));
    RingBuffer_Init(&p_vuart->core0_tx_core1_rx,p_vuart->core0_tx_core1_rx_buff,sizeof(p_vuart->core0_tx_core1_rx_buff));
    
    /* init magic value */
    p_vuart->magic[0]  = 'V';
    p_vuart->magic[1]  = 'U';
    p_vuart->magic[2]  = 'R';
    p_vuart->magic[3]  = 'T';    
    
}

#endif


int main(void)
{


    
    MAILBOX_Init(MAILBOX);
    NVIC_EnableIRQ(MAILBOX_IRQn);

#ifdef APP_USING_VIRTUAL_UART    
    virual_uart_init(&virual_uart0);
    rt_kprintf("send to core1 virual uart addr %x.\n",(uint32_t)(&virual_uart0));
    MAILBOX_SetValue(MAILBOX,kMAILBOX_CM33_Core1,(uint32_t)(&virual_uart0)); 
#endif
    

}

 

CORE1 侧将对应的log 输出函数 本地使用的printf  底层IO接口输出写入到Ringbuff

size_t __write(int handle, const unsigned char *buffer, size_t size)
{

     while(MAILBOX_GetMutex(MAILBOX) == 0);
      

     RingBuffer_Write(&p_virtual_uart0->core0_rx_core1_tx,(uint8_t *)buffer,size);       

     MAILBOX_SetMutex(MAILBOX);
     
     return size;
}


CORE0 侧读取对应的Ringbuff 并将数据转发至UART 物理层,对应代码如下。

int main(void)
{
    while (1)
    {
        uint8_t data;
        //rt_pin_write(LEDB_PIN, PIN_HIGH);    /* Set GPIO output 1 */
        //rt_thread_mdelay(500);               /* Delay 500mS */
        //rt_pin_write(LEDB_PIN, PIN_LOW);     /* Set GPIO output 0 */
        //rt_thread_mdelay(500);               /* Delay 500mS */
        while(MAILBOX_GetMutex(MAILBOX) == 0);
        
        while(RingBuffer_GetDataLength(&virual_uart0.core0_rx_core1_tx))
        {
            RingBuffer_Read(&virual_uart0.core0_rx_core1_tx,&data,1);
            rt_kprintf("%c",data);
        }
      
        MAILBOX_SetMutex(MAILBOX);
        
        rt_thread_mdelay(10);
    }
}

至此代码已经适配完成,在 CORE1 侧调用printf 函数验证虚拟串口的功能。

/*!
 * @brief Main function
 */
int main(void)
{
    
    while(p_virtual_uart0 == NULL);
    
    if(p_virtual_uart0->magic[0] == 'V' && 
       p_virtual_uart0->magic[1] == 'U' && 
       p_virtual_uart0->magic[2] == 'R' && 
       p_virtual_uart0->magic[3] == 'T')
    {
        printf("\r\n [core1] virtual uart init ok.\r\n");
    }

    /* Configure LED */
    LED_INIT();
    

    for (;;)
    {
        SDK_DelayAtLeastUs(500000U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
        LED_TOGGLE();
        printf("\r\n [core1] led toggle.\r\n");
    }

}

 运行发现core0 和 core1 的log 都按照预期的在uart 上输出显示了,至此已经完成上述通过share memory 来虚拟串口显示log 的功能。

image.png


专家
2024-11-17 00:41:20     打赏
2楼

谢谢分享


专家
2024-11-28 14:17:10     打赏
3楼

每个核能控制运营与否吗?


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]