DSP- 6678--------- 多核DSP图像处理(2)主核程序之tsk_master_func进程

一、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\n");
    }

    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\n" );
    }
    /* 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\n" );
    }

    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\n");
        }


	 /*===================================================================================
	 *			邮箱发送传递的数据: 数据指针和长度,处理时间,处理结果
	 *=================================================================================== */
        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\n");
        }

    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\n");
     return;
}

3.2 图像处理调度过程  mc_process_bmp

<1> 读取图片像素

	if (bmp_read_header(p_input_image, &bmp_header) < 0)  //读取图片信息,填充bmp_header
	{
		printf("Error in reading header\n");
		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\n");
			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\n");
			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\n");
		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\n");
		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\n" );
	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]\n", 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]\n", 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]\n", 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\n");
    	    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\n");
    		ret_val = -1;
        }
        else if (p_msg->info.flag != 0)
        {
            printf("Process image error received from core %d\n", 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\n");
		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\n");
	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\n");
	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\n");
      return;
}

程序下载地址

https://download.csdn.net/download/yunge812/10517028

猜你喜欢

转载自blog.csdn.net/yunge812/article/details/80896549
dsp