基于Keil双核架构的研究3 -共享内存 1. 设计思想在Core0和Core1之间开辟一段SRAM,作为双核之间数据传递的共用内存。以Core0的RPMSG通讯作为触发信号,填充共享内存段的数据,然后Core1通过RPMSG信息通知Core0接收数据。这种方式对于传输数据频率较低,但传输数据量很大时还是非常有效的。 2. 软件实践利用前次RPMSG-Lite的试验的结果,重新规划设计内存的试用情况,从0x20039800开始到0x20040000止,大约26K的内存空间用来作为核间通讯的共享内存。 - <div align="left"> #define DATA_SH_MEM_ADDR 0x20039800</div><div align="left"> #defineDATA_SH_MEM_SIZE 0x6800</div>
复制代码
构建一个结构体指针,用来管理共享内存。根据实际需要,可以将这段内存再次划分为多个段。
- typedef struct
- {
- uint32_t type;
- uint8_t dat[100];
- uint16_t crc;
- }*DATA_SH_MEM_PTR;
- DATA_SH_MEM_PTR data_sh_mem_ptr = (DATA_SH_MEM_PTR)DATA_SH_MEM_ADDR;
复制代码
这里假设这种类型的结构体和使用方法。
Core1在接收到Core0发送的rpmsg信息后,在rpmsg的回调函数中填充共享内存,并且对填入的数据形成校验:
- /*Internal functions */
- staticint32_t my_ept_read_cb(void *payload, uint32_t payload_len, uint32_t src, void*priv)
- {
- int32_t *has_received = priv;
- int i;
- uint16_t crc = 0;
- if (payload_len <= sizeof(THE_MESSAGE))
- {
- (void)memcpy((void*)&msg, payload, payload_len);
- remote_addr = src;
- *has_received = 1;
- data_sh_mem_ptr->type= 0x01; //type
- for(i=0;i<100;i++)
- {
- data_sh_mem_ptr->dat =(uint8_t)msg.DATA;
- crc +=data_sh_mem_ptr->dat;
- }
- data_sh_mem_ptr->crc= crc;
- }
- return RL_RELEASE;
- }
- 在主循环中,查看是否完成数据填充,完成填充后,发送rpmsg消息通知Core0进行共享内存数据解析。
- Core0在接收到Core1的rpmsg后,在回调函数中解析共享内存数据,并进行校验:
- <p>/* This is the read callback,note we are in a task context when this callback</p><p>is invoked, so kernelprimitives can be used freely */</p><p>static int32_tmy_ept_read_cb(void *payload, uint32_t payload_len, uint32_t src, void *priv)</p>{
- int32_t *has_received = priv;
- int i;
- uint16_t crc = 0;
- if (payload_len <= sizeof(THE_MESSAGE))
- {
- if(data_sh_mem_ptr->type == 0x01)
- {
- data_sh_mem_ptr->type = 0x00;
- for(i=0;i<100;i++)
- crc += data_sh_mem_ptr->dat;
- if(crc == data_sh_mem_ptr->crc)
- {
- <p>// (void)PRINTF("Primary corereceived sh mem data success\r\n");</p><p> (void)PRINTF("ss:DATA =%i\r\n", data_sh_mem_ptr->dat[0]);</p> }
- else
- {
- <p>// (void)PRINTF("Primary corereceived sh mem data failed\r\n");</p><p> (void)PRINTF("ff:crc0 = %ucrc1= %u \r\n", crc,data_sh_mem_ptr->crc);</p> }
- }
- <p> (void)memcpy((void *)&msg, payload,payload_len);</p> *has_received = 1;
- }
- count++;
- return RL_RELEASE;
- }
复制代码
当Core0完成共享内存信息处理后,即完成一次Core0和Core1核间数据交换。Core0可以随即发起下一次数据交换,也可以采用周期性的方式触发下一次的数据交换。
为了保证数据传输的速度,不采用rpmsg数据同步,而是采用环形队列的方式管理共享内存空间,如果Core0查询的速度和环形队列空间的适当控制,可以保证实时数据传递,进行在一个CPU内部一样。
3. 效果验证
|