一、cfg文件配置
var tskMainThread = Task.create("&StartNetworkTask"); /*创建TCP进程*/
tskMainThread.stackSize = 0x2000;
tskMainThread.priority = 0x5;
tskMainThread.instance.name = "StartNetworkTask";
创建TCP进程 用于从上位机发送和接收图像。将在下一节中介绍
二、main函数
2.1 网络初始化
GbE_init();
2.2 IPC开启
status = Ipc_start();
if (status < 0)
{
System_abort("Ipc_start failed
");
}
2.3 创建heapBuf
HeapBufMP_Params_init(&heapBufParams);
heapBufParams.regionId = 0;
heapBufParams.name = IMAGE_PROCESSING_HEAP_NAME;//name用于open函数指定打开
heapBufParams.numBlocks = number_of_cores;
heapBufParams.blockSize = sizeof(process_message_t);
heapHandle = HeapBufMP_create(&heapBufParams);
if (heapHandle == NULL)
{
System_abort("HeapBufMP_create failed
" );
}
/* Register this heap with MessageQ */
status = MessageQ_registerHeap((IHeap_Handle)heapHandle, IMAGE_PROCESSING_HEAPID);
if(status != MessageQ_S_SUCCESS)
{
System_abort("Main: MessageQ_registerHeap failed
" );
}
System_abort("Main: MessageQ_registerHeap failed
" );
}
2.4 初始化一些参数
1 给8个核的msg指针分配空间
2 给8个核MessageQ_alloc
3 初始化slave_queue_name
2.5 创建 接收和发送的mailbox
/*===================================================================================
* 邮箱接收的数据: 边缘检测,数据指针和长度,核个数
*=================================================================================== */
master_mbox_receive = Mailbox_create (sizeof(mbox_process_msg_t), 1, 0, 0); //返回值Mailbox_Handle
if(!master_mbox_receive)
{
System_printf("main: Mailbox creation failed for master_mbox_receive
");
}
/*===================================================================================
* 邮箱发送传递的数据: 数据指针和长度,处理时间,处理结果
*=================================================================================== */
master_mbox_send = Mailbox_create (sizeof(mbox_response_msg_t), 1, 0, 0); //返回值Mailbox_Handle
if(!master_mbox_send)
{
System_printf("main: Mailbox creation failed for master_mbox_send
");
}
2.6 创建第二个进程 tsk_master_func
/* Create a unique 'master' Task if on proc 0 */
Task_Params_init(¶ms);
params.stackSize = 0x2000;
params.priority = 7;
Task_create(tsk_master_func, ¶ms, NULL);
本节主要进行该进程的介绍
2.7 BIOS_start( )
三、tsk_master_func进程
3.1 等上位机传递来的mailbox
/*等邮箱消息 上位机通过TCP会发送图片给DSP DSP收到之后会产生 Mailbox_post 这里的Mailbox_pend就是在等待这个Mailbox_post */
if (Mailbox_pend(master_mbox_receive, &process_msg, BIOS_WAIT_FOREVER) == FALSE)
{
System_printf("main: Mailbox_pend returns error
");
return;
}
3.2 图像处理调度过程 mc_process_bmp
<1> 读取图片像素
if (bmp_read_header(p_input_image, &bmp_header) < 0) //读取图片信息,填充bmp_header
{
printf("Error in reading header
");
ret_val = -1;
goto close_n_exit;
}
pixel_size = bmp_header.dib.bits_per_pixel / 8; //每一个像素的字节数 pixel_size = BPP/8
row_width = bmp_header.dib.image_width * pixel_size; //行宽(单位为字节)
if (bmp_header.dib.number_of_colors)
{
/* Color table present */
color_table_size = ROUNDUP(sizeof(bmp_color_table_t) * bmp_header.dib.number_of_colors, MAX_CACHE_LINE);
p_color_table = (bmp_color_table_t *)Memory_alloc(0, color_table_size, MAX_CACHE_LINE, NULL);
if(!p_color_table)
{
printf("Can't allocate memory for color table
");
ret_val = -1;
goto close_n_exit;
}
if (bmp_read_colormap(p_input_image, &bmp_header, p_color_table) < 0)
{
printf("Error in reading color map
");
ret_val = -1;
goto close_n_exit;
}
Cache_wb(p_color_table, color_table_size, Cache_Type_ALL, FALSE);
}
/* Read the pixels */
pixel_array_rgb_size = ROUNDUP(bmp_header.dib.image_height * row_width, MAX_CACHE_LINE); //整个图片的大小 (单位 字节)
pixel_array_rgb = (uint8_t *) Memory_alloc(0, pixel_array_rgb_size, MAX_CACHE_LINE, NULL); //该指针指向的地址存储整个图片的像素
if (!pixel_array_rgb)
{
printf("Can't allocate memory for pixel_array_rgb
");
ret_val = -1;
goto close_n_exit;
}
/*===================================================================================================
* 读取BMP图像信息 从 p_input_image提取出头部信息 存放在pixel_array_rgb中
* rgb[n]指向pixel_array_rgb rgb
*=================================================================================================== */
//将p_input_image.data ==> pixel_array_rgb中
if (bmp_read_image (p_input_image, &bmp_header, pixel_array_rgb) < 0)
{
printf("Error in reading pixel image
");
ret_val = -1;
goto close_n_exit;
}
Cache_wb(pixel_array_rgb, (bmp_header.dib.image_height * row_width), Cache_Type_ALL, FALSE);
p_input_image为输入的bmp图像,首先提取出bmp的头部信息,存储在bmp_header处,pixel_array_rgb为提取出的图像。
<2> messageQ_create( master )
h_receive_queue = MessageQ_create(MASTER_QUEUE_NAME, NULL);
if (h_receive_queue == NULL)
{
printf("MessageQ_create failed
" );
ret_val = -1;
goto close_n_exit;
}
这里创建的messageQ是用来接收从核发送过来的数据的。
<3> messageQ_open( slave )
打开slave核创建的messageQ
for (j = 0; j < number_of_cores; j++)
{
do {
i = MessageQ_open(slave_queue_name[j], &queue_id[j]);
} while (i < 0);
}
<4>
给每一个核分配相应的图片像素
rgb[i]指向每个核要处理图像数据的第一个像素 height[i]代表每一个核处理的高度,由于要进行sobel运算,因此每个核之间有重复的部分
slice_height = bmp_header.dib.image_height / number_of_cores;// H/8
rgb[0] = &(pixel_array_rgb[0]);
height[0] = slice_height + guard_height; //第一个height只能重复下面的一行
for (i = 1; i < number_of_cores; i++)
{
rgb[i] = pixel_array_rgb + ((i * slice_height * row_width) - (row_width * guard_height)); //指针指向每个核分配的像素的首地址
height[i] = slice_height + (2 * guard_height); //每个核单独处理的高度+上下重复的两行
}
height[number_of_cores - 1] = slice_height + guard_height; //最后一个height只能重复上面的一行
<5> 对存储sobel数据的区域进行分配空间 对p_queue_msg->info.scratch_buf[0]进行分配空间
for (i = 0; i < number_of_cores; i++)
{
edge_size[i] = ROUNDUP((height[i] * row_width), MAX_CACHE_LINE); //每一个核需要占用的空间的大小
edge[i] = (uint8_t *) Memory_alloc(0, edge_size[i], MAX_CACHE_LINE, NULL); //最后的边缘检测结果
if (!edge[i])
{
printf("mc_process_bmp: Memory_alloc failed for edge[%d]
", i);
ret_val = -1;
goto close_n_exit;
}
/* Allocate scratch buffers for slave processors */
p_queue_msg[i]->info.scratch_buf[0] =
(uint8_t *) Memory_alloc(0, ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE), MAX_CACHE_LINE, NULL);
if(!p_queue_msg[i]->info.scratch_buf[0])
{
printf("mc_process_bmp: Memory_alloc failed for scratch_buf[%d][0]
", i);
ret_val = -1;
goto close_n_exit;
}
p_queue_msg[i]->info.scratch_buf_len[0] = ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE);
if ((p_color_table) || (bmp_header.dib.bits_per_pixel != 8))
{
p_queue_msg[i]->info.scratch_buf[1] =
(uint8_t *) Memory_alloc(0, ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE), MAX_CACHE_LINE, NULL);
if(!p_queue_msg[i]->info.scratch_buf[1])
{
printf("mc_process_bmp: Memory_alloc failed for scratch_buf[%d][1]
", i);
ret_val = -1;
goto close_n_exit;
}
p_queue_msg[i]->info.scratch_buf_len[1] = ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE);
}
}
ret_val = -1;
goto close_n_exit;
}
/* Allocate scratch buffers for slave processors */
p_queue_msg[i]->info.scratch_buf[0] =
(uint8_t *) Memory_alloc(0, ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE), MAX_CACHE_LINE, NULL);
if(!p_queue_msg[i]->info.scratch_buf[0])
{
printf("mc_process_bmp: Memory_alloc failed for scratch_buf[%d][0]
", i);
ret_val = -1;
goto close_n_exit;
}
p_queue_msg[i]->info.scratch_buf_len[0] = ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE);
if ((p_color_table) || (bmp_header.dib.bits_per_pixel != 8))
{
p_queue_msg[i]->info.scratch_buf[1] =
(uint8_t *) Memory_alloc(0, ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE), MAX_CACHE_LINE, NULL);
if(!p_queue_msg[i]->info.scratch_buf[1])
{
printf("mc_process_bmp: Memory_alloc failed for scratch_buf[%d][1]
", i);
ret_val = -1;
goto close_n_exit;
}
p_queue_msg[i]->info.scratch_buf_len[1] = ROUNDUP(bmp_header.dib.image_width * height[i], MAX_CACHE_LINE);
}
}
这里必须进行分配空间 因为msg的信息中需要传递这些数据的指针。
<6> 构建messageQ的msg结构体
<7> 将messageQ放入队列 发送messageQ( slave )
for (i = number_of_cores-1; i >= 0; i-- )
{
p_msg = p_queue_msg[i];
p_msg->core_id = i;
p_msg->info.processing_type = edge_detection;
p_msg->info.bitspp = bmp_header.dib.bits_per_pixel;
p_msg->info.p_color_table = (color_table_t*) p_color_table;
p_msg->info.width = bmp_header.dib.image_width;
p_msg->info.height = height[i];
p_msg->info.rgb_in = rgb[i];
p_msg->info.out = edge[i];
p_msg->info.flag = 0;
MessageQ_setMsgId(p_msg, ++msgId);
//将message插入队列
MessageQ_setReplyQueue(h_receive_queue, (MessageQ_Msg)p_msg); //MessageQ_open
/* send the message to the remote processor */
if (MessageQ_put(queue_id[i], (MessageQ_Msg)p_msg) < 0)
{
printf("MessageQ_put had a failure error
");
ret_val = -1;
goto close_n_exit;
}
}
这里的发送 对应的是第三步的打开slave messageQ
<8> 等待8个核的处理结果 messageQ_get(master)
for (i = 0; i < number_of_cores; i++)
{
if (MessageQ_get(h_receive_queue, (MessageQ_Msg *)&p_msg, MessageQ_FOREVER) < 0)
{
printf("This should not happen since timeout is forever
");
ret_val = -1;
}
else if (p_msg->info.flag != 0)
{
printf("Process image error received from core %d
", i);
ret_val = -1;
}
}
<9>融合图像,输出
处理完的结果通过messageQ传递给主核,传递过来的是sobel的地址参数。
pixel_array_edge_size = bmp_header.dib.image_width * bmp_header.dib.image_height;
pixel_array_edge = (uint8_t *) Memory_alloc(0, pixel_array_edge_size, 0, NULL);
if (!pixel_array_edge)
{
printf("Can't allocate memory for pixel_array_edge
");
ret_val = -1;
goto close_n_exit;
}
memcpy(&(pixel_array_edge[0]), &(edge[0][0]), slice_height * bmp_header.dib.image_width);
if (number_of_cores > 1)
{
for (i = 1; i < number_of_cores; i++)
{
Cache_inv(edge[i], (p_msg->info.height * p_msg->info.width), Cache_Type_ALL, FALSE);
memcpy(pixel_array_edge + (i * slice_height * bmp_header.dib.image_width),
edge[i] + (bmp_header.dib.image_width * guard_height), slice_height * bmp_header.dib.image_width);
}
}
p_output_image->length = bmp_get_gray_bmpfile_size(bmp_header.dib.image_width, bmp_header.dib.image_height);
p_output_image->data = (uint8_t *) Memory_alloc(0, p_output_image->length, 0, NULL);
if (!p_output_image->data)
{
p_output_image->length = 0;
printf("Can't allocate memory for output bmp image
");
ret_val = -1;
goto close_n_exit;
}
/* Create (Gray Scale) Image */
if (bmp_write_gray_bmpfile (p_output_image, pixel_array_edge,
bmp_header.dib.image_width, bmp_header.dib.image_height) < 0)
{
printf("Error in bmp_write_gray_bmpfile
");
ret_val = -1;
goto close_n_exit;
}
融合各个核的处理结果
1 edge => pixel_array_edge
2 pixel_array_edge => p_output_image
3 填充p_output_image结构体
3.3 Mailbox_post( )
数据处理完毕之后 post邮箱 接到post信号之后TCP向上位机传送数据
if (Mailbox_post(master_mbox_send, &response_msg, BIOS_WAIT_FOREVER) == FALSE)
{
System_printf("main: Mailbox_post returns error
");
return;
}
程序下载地址
https://download.csdn.net/download/yunge812/10517028
=======================================================================
最近新开的公众号,文章正在一篇篇的更新,
公众号名称:
玩转电子世界
各位朋友有什么问题了可以直接在上面提问,我会一一进行解答的。
跟着阳光非宅男,一步步走进电子的世界。
关注之后回复 资料下载 关键词可以获得
免费海量的视频学习资料下载~~!
已共享的学习视频资料,共享资料正在不断更新中。。。
=======================================================================