树莓派3B——Mailbox

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cj675816156/article/details/86027172

概述

Mailbox有助于ARM和VideoCore之间的通信。下面列出了可用Mailbox/channel。每个Mailbox都是一个8位深的32位字FIFO,可由ARM和VC读取/写入。只有Mailbox 0的状态可以触发ARM上的中断,因此Mailbox 0始终用于从VC到ARM的通信,Mailbox 1用于ARM到VC。ARM永远不应该写Mailbox 0或读Mailbox 1。
树莓派Mailbox0和Mailbox1通信流程:

Mailbox0
GPU
Cortex-a53
Mailbox1
Cortex-a53
GPU

Channel(通道)

下面列出了当前定义的Mailbox通道,其中包含指向描述消息格式的页面的链接。
邮箱0定义以下渠道:
0:电源管理
1:帧缓冲
2:虚拟UART
3:VCHIQ
4:LED
5:按钮
6:触摸屏
7:属性标签(ARM - > VC)
8:属性标签(VC - > ARM)

Mailbox寄存器

以下给出了Mailbox各个寄存器的地址偏移量,MailBox0的基地址是0x3F00B880,Mailbox使用和配置流程详见:
这里

#define VIDEOCORE_MBOX (0x3F00B880)
#define MAILBOX0_READ ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x00))
#define MAILBOX0_PEEK ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x10))
#define MAILBOX0_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x14))
#define MAILBOX0_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x18))
#define MAILBOX0_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x1C))
#define MAILBOX1_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x20))
#define MAILBOX1_PEEK ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x30))
#define MAILBOX1_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x34))
#define MAILBOX1_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x38))
#define MAILBOX1_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x3C))
#define ARM_MS_FULL BIT(31)
#define ARM_MS_EMPTY BIT(30)
#define ARM_MC_IHAVEDATAIRQEN BIT(0)

树莓派Mailbox访问一般流程:

要从邮箱中读取:
1、读取状态寄存器,直到没有设置empty标志
2、从读寄存器读取数据
3、如果低4位与所需的通道编号不匹配,则从1开始重复
4、高28位是返回的数据
写入邮箱:
1、读取状态寄存器,直到未设置full标志
2、将数据(移入高28位)与通道(低4位)一起写入写寄存器
还有一些注意详见:这里
MailBox接口编码查询详见:这里

树莓派Mailbox数据包格式


  • U32: 整个数据包大小,单位字节(包括头,end标记和字节对齐填充)
  • U32: 请求/回复代码
    • 请求代码:

      • 0x00000000: process request
    • 回复代码:

      • 0x80000000: 请求成功
      • 0x80000001: error

tag有如下格式:

  • U32: tag identifier
  • U32: value buffer size, 单位字节
  • U32:
    • 请求代码:
      • b31: 0
      • b30-b0: reserved
    • 回复代码:
      • b31: 1
      • b30-b0: value length, 单位字节
  • U8…: value buffer
  • U8…: 整个tag以32字节对齐

  • U32: 0x0 (end tag)
  • U8…: padding

示例代码

#include "reg.h"
#include "uart.h"

 #define VIDEOCORE_MBOX (0x3F00B880)
#define MAILBOX0_READ   ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x00))
#define MAILBOX0_PEEK   ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x10))
#define MAILBOX0_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x14))
#define MAILBOX0_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x18))
#define MAILBOX0_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x1C))
#define MAILBOX1_WRITE  ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x20))
#define MAILBOX1_PEEK   ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x30))
#define MAILBOX1_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x34))
#define MAILBOX1_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x38))
#define MAILBOX1_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX + 0x3C))
#define ARM_MS_FULL           BIT(31)
#define MBOX_RESPONSE         BIT(31)
#define ARM_MS_EMPTY          BIT(30)
#define ARM_MC_IHAVEDATAIRQEN BIT(0)

#define MBOX_REQUEST    0

 /* channels */
#define MBOX_CH_POWER   0
#define MBOX_CH_FB      1
#define MBOX_CH_VUART   2
#define MBOX_CH_VCHIQ   3
#define MBOX_CH_LEDS    4
#define MBOX_CH_BTNS    5
#define MBOX_CH_TOUCH   6
#define MBOX_CH_COUNT   7
#define MBOX_CH_PROP    8

 /* tags */
#define MBOX_TAG_GETSERIAL      0x10004
#define MBOX_TAG_LAST           0

 #define ALIGN(n) __attribute__((aligned(n)))

 /* mailbox message buffer */
volatile unsigned int mbox_buffer[64] ALIGN(16);

 int mailbox_call(unsigned char channel)
{
	unsigned int address = (unsigned int)(((unsigned long)mbox_buffer & ~0xF) | (channel & 0xF));

 	puts("mailbox_call check prewrite\n");
	while (*MAILBOX1_STATUS & ARM_MS_FULL);

 	*MAILBOX1_WRITE = address;

 	while (1) {
		puts("mailbox_call check preread\n");
		while (*MAILBOX0_STATUS & ARM_MS_EMPTY);

 		puts("mailbox_call reading\n");
		if (address == *MAILBOX0_READ)
			return mbox_buffer[1] == MBOX_RESPONSE;
	}
	puts("mailbox_call error\n");
	return 0;
}

 void get_serial(void)
{
	mbox_buffer[0] = 8 * 4;
	mbox_buffer[1] = MBOX_REQUEST;
	mbox_buffer[2] = MBOX_TAG_GETSERIAL; // tag identifier
	mbox_buffer[3] = 8; // buffer size
	mbox_buffer[4] = 8; // buffer size
	mbox_buffer[5] = 0; // clear buffer data
	mbox_buffer[6] = 0; // clear buffer data
	mailbox_call(MBOX_CH_PROP);
	puts("My serial number is\n");
	hex(mbox_buffer[6]);
	hex(mbox_buffer[5]);
}

猜你喜欢

转载自blog.csdn.net/cj675816156/article/details/86027172