zoukankan      html  css  js  c++  java
  • RT600之Mailbox

    Mailbox是NXP LPC系列产品新推的一项功能。Debugger可以通过mailbox与ROM通信,实现Flash Erase、Enter ISP mode、debug authentication等功能。

    Mailbox架构图

    Mailbox 寄存器

    Mailbox有三个寄存器

    • CSW(Command status and Word register)
      Debugger可以通过这个寄存器指示ROM进到mailbox handler,ROM、Debugger可以通过这个寄存器获知通信状况。
    • Request register
      Debugger向这个寄存器写入数据,ROM从该寄存器中获取数据执行相应的操作。
    • Return register
      ROM向此寄存器写入数据,debugger可以从该寄存器获取ROM的信息。

    SWD访问mailbox示意图

    SWD访问APB-AP,实现跟Mailbox的通信

    • AP: Access Port。 绿色圈内所示连接到Mailbox
    • DP: Debug Port。 就是我们的Jlink

    ROM Mailbox Handler功能解析

    Request/Response机制

    Mailbox基于Request/Response机制,如下图:

    • Debugger向CSW写入0x21,申请re-sync同时reset
    • ROM检测CSW re-sync被置1,进入mailbox handler,向response寄存器写入0x0.等待debugger的请求。
    • Debugger向request寄存器写入数据
    • ROM获取reqeust寄存器中的数据,根据不同的指令进行相应的处理(比如擦除flash),向response寄存器中写入数据。
    • Debugger可以根据response寄存器中的数据判断指令是否执行成功

    ROM支持的Mailbox指令

    • START_DBG_MB - 0x0001
    • GET_CRP_LEVEL - 0x0002, Deprecated ans return 3
    • ERASE_FLASH - 0x0003,
    • EXIT_DBG_MB - 0x0004,
    • ENTER_ISP_MODE - 0x0005,
    • SET_FA_MODE - 0x0006,
    • DBG_AUTH_START - 0x0010
    • DBG_AUTH_RESP - 0x0011

    ROM Error Defination

    ERR_DM_BASE = 0x00100000,
    
    ERR_DM_NOT_ENTERED = ERR_DM_BASE + 1, /*0x00100001*/
    ERR_DM_UNKNOWN_CMD = ERR_DM_BASE + 2, /*0x00100002*/
    ERR_DM_COMM_FAIL = ERR_DM_BASE + 3,   /*0x00100003*/
    

    SWD访问Mailbox流程

    以进入ISPmode为例

    1. Debugger选择APB-AP,访问mailbox
    2. Debugger向CSW写入0x21,申请re-sync同时reset
    3. ROM检测到re-sync信号,reset mailbox,进入mailbox handler,等待debugger的指令
    4. Debugger发送0x10005至request寄存器(如上如示ENTER_ISP_MODE = 0x5,高16bit为1表示通知ROM接下来还要发送一个参数,ROM根据这个参数使用相应的peripheral进入ISP)
    5. ROM读取request寄存器中数据,发现需要一个参数,向reponse寄存器中写入0x1A5A5。告知debugger其已经获知需要一个参数
    6. Debugger向request寄存器发送0x7(Use UARTSPII2C进入ISP mode)
    7. ROM检测SOCU是否使能了ISPCMDENROM,如果是则向response写入0x0然后根据参数0x7进入ISP mode。否则向response写入ERR_DM_UNKNOWN_CMD

    发送Authen Start命令获取数据

    • Debugger向ROM发送authen start命令后,接下来向ROM发送索取数据的长度+0xA5A5. authentication结构体的长度是0x1A,
    • Debugger发送0x1AA5A5后,ROM会检测低16bits是否为0xA5A5并校验长度是否为0x1A,正确后发送一个word的数据给debugger
    • Debuuger获取到数据后,长度减1未0x19A5A5,再次请求获取数据
    • ROM检测低16bits是否为0xA5A5并且校验长度是否为0x19,通过后返回一个word的数据给Debugger
    • 直到Debugger发送0xA5A5告知ROM数据已经全部获取后,ROM停止数据的发送

    ROM发送的数据结构体如下:

    typedef struct __attribute__ ((packed)) debug_auth_version {
        uint16_t major;
        uint16_t minor;
    } debug_auth_version_t;
    
    typedef struct __attribute__ ((packed)) debug_auth_challenge {
        debug_auth_version_t version;
        uint32_t socc; 
        uint32_t device_uuid[4];
        debug_rotid_t rotid;
        uint32_t cc_socu_pinned;
        uint32_t cc_socu_default;
        uint32_t cc_vu;
        uint8_t challengeVector[32];
    } debug_auth_challenge_t;
    

    Debugger发送Authen response命令向ROM发送数据

    以证书长度为2048bit长度的case为例:

    • Debugger向ROM发送0x12C0011,请求向ROM发送认证数据。0x12C为证书长度为2048bit时,ROM需要的认证数据的长度
    • ROM接到认证请求后,返回需要认证数据的长度0x12C+0xA5A5
    • Debugger发送数据
    • ROM接到数据后,长度减1,返回0x12BA5A5
    • 所有数据传送完毕后,ROM返回0,然后进行认证

    示例Code

    使用Python撰写,调用pylink实现debugger跟mailbox的通信

    import pylink  
    import pylink.protocols.swd as swd  
    from time import sleep  
    
    class jlink(object):  
    def __init__(self):  
    	self.jlink = pylink.JLink()  
    	self.jlink.target_connection_required = False  
    	self.jlink.open()  
    	self.jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)#select APB-AP to communicate with mailbox   
    	self.jlink.coresight_configure()  
    
    	request = swd.WriteRequest(2, data=(0x000000F0 | (2 << 24)),  ap=False)  
    	response = request.send(self.jlink)  
    	assert response.ack(), "No ack from JLink"  
    
    	request = swd.WriteRequest(2, data=(0x00000000 | (2 << 24)), ap=False)
    	response = request.send(self.jlink)
    	assert response.ack(), "No ack from JLink"
    
    def swd_write(self, addr, value):
    	request = swd.WriteRequest(addr/4, data = value, ap = True)
    	response = request.send(self.jlink)
    	assert response.ack(), "No ack from JLink"
    	print('send value to addr 0x%x'%addr)
    	print('value is 0x%x'%value)
    
    def swd_read(self, addr):
    	request = swd.ReadRequest(addr/4, ap = True)
    	response = request.send(self.jlink)
    	assert response.ack(), "No ack from JLink"
    	sleep(0.1)
    	request2 = swd.ReadRequest(3, ap = False)
    	response2 = request2.send(self.jlink)#read data from DP register3, not got data correctly from response register
    	print ("read data: 0x%08x"%response2.data)
    #start neter into mailbox  
    jlink = jlink()  
    jlink.swd_write(0, 0x21)  
    jlink.swd_read(0)  
    
    #enter isp mode
    jlink.swd_write(4, 0x100005)
    sleep(1)
    jlink.swd_read(8)
    jlink.swd_write(4, 0x7)
    sleep(1)
    jlink.swd_read(8)
  • 相关阅读:
    近期安卓与IOS招聘面试有感
    java线程池技术(二): 核心ThreadPoolExecutor介绍
    java线程池技术(一):ThreadFactory与BlockingQueue
    Java设计模式之策略模式与状态模式
    java线程间通信:一个小Demo完全搞懂
    Android M 新的运行时权限开发者需要知道的一切
    Java多线程同步问题:一个小Demo完全搞懂
    java多线程之守护线程以及Join方法
    安卓电量优化之JobScheduler使用介绍
    安卓电量优化之WakeLock锁机制全面解析
  • 原文地址:https://www.cnblogs.com/richard-xiong/p/10041482.html
Copyright © 2011-2022 走看看