spinlock测试说明文档
spinlock简介
自旋锁(spinlock)是为了实现保护共享资源而设计的一个IP,实现了在任何时刻某个共享资源只能被一个master访问。
在自旋锁机制中,某个master要访问某个共享资源时,首先查询该共享资源是否被其他的master访问,即是否已经被其他的master锁住,如果没有,则该master先对该共享资源上锁,然后在执行对共享资源的操作,在访问结束之后主动释放锁。如果已经被其他的master锁住,则一直查询该贡献资源是否已经被其他master释放。
在kl3中,自旋锁的本质是一个32bit的寄存器,一共16个自旋锁(即最多定义16个共享资源),每个自旋锁的每个bit对应一个master,这些寄存器具有如下特性:
-
存在保护寄存器,通过写入magic number到指定的寄存器来解除保护,仅在解除保护的情况下才能写自旋锁对应的寄存器。
-
在自旋锁寄存器已经有bit被置1的情况下,无法再对其他的bit进行置1操作,此时必须将所有已经置1的bit清除之后,才能重新置位其他的bit。
spinlock测试例程说明
spinlock测试例程使用到的外设包含spinlock、uart、gp_timer。
- spinlock:测试对象,用于测试spinlock对贡献资源的保护功能。
- uart:使用uart0,实现调试信息打印,接收case配置信息等与PC的交互功能。
- gp_timer:用于定时。
spinlock测试例程遵循自动化测试框架,在例程执行之后,初始化串口0,通过串口发送“start”字段到PC,并等待PC发送“config”字段来获取本次需要执行的测试case。
在获取到case组合之后,初始化spinlock,并根据case组合开始执行测试case。
case0:共享资源保护测试
spinlock功能比较单一,因此测试例程比较简单,仅以ram中的一个地址作为共享资源(事实上这里的串口也是共享资源),3个核同时对该地址进行读写操作,观察数据是否正确,以及core是否一直等待spinlock。具体步骤如下:
-
上电后初始化外设,并将ram指定地址的数据清零。
-
引导core1、core2运行测试代码,并记录此时gp_timer的计数值
core1、core2测试代码一致,都是运行之后马上申请spinlock,在拿到锁之后,对ram地址进行读写操作,每次在原有数据的基础上加1,每次读写操作延时100ms,在执行100次读写后释放spinlock,并将core挂起。
为了保证core0最后执行,core0在启动core1、core2之后延时一段时间(这段时间比core1、core2执行的总时长要更短)
-
core0申请spinlock,在拿到锁之后,读取gp_timer的时间,并判断执行时间与core1、core2延时总时长差距是否过大,同时判断ram中的数据是否为其他core累加的值。如果任意条件不满足,则判定失败。
测试结果符合预期。core1、core2顺序执行(先后顺序不一定),core会一直等待spinlock,并能正确的保护资源。