3

STM32H5移植zbar记录 - Jayson_Ge

 11 months ago
source link: https://www.cnblogs.com/uplaoding-ing/p/17431144.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

STM32H5移植zbar记录

ZBar是一种流行的二维码扫描和解码工具,它在嵌入式系统中拥有广泛的应用。在嵌入式系统中,我们面临着有限的资源和更严格的性能要求,因此,选择适当的库来完成特定的任务非常重要。
ZBar适用于各种嵌入式平台,包括ARM、x86和MIPS等处理器架构。它可以轻松地整合到各种嵌入式系统中,如智能家居设备、智能手机、平板电脑、远程控制设备、工业控制器等。
ZBar使用C/C++编写,具有高度优化的算法,能够快速准确地读取各种二维码和条形码,包括QR码、Data Matrix码、PDF417码、EAN-13码等等。同时,ZBar还支持自定义解码器,开发者可以根据自己的需求配置扫描器以实现更好的解码效果。
ZBar还具有非常灵活的API,可用于C/C++、Python、Java、Ruby等语言,开发人员可以根据自己的需求灵活选择相应的API。此外,ZBar还支持多种操作系统和平台,包括Linux、Windows、Mac OS X等。
总之,ZBar是一种非常有用的嵌入式二维码和条形码扫描库,它提供了高效的解码算法、可定制的解码器和灵活的API,能够轻松地满足嵌入式设备的扫描和解码需求。

这里感谢之前大佬移植zbar库到stm32,具体链接如下:https://www.cnblogs.com/greyorbit/p/8456814.html

移植步骤也很简单,按照博文把对应文件和头文件路径加入到工程中,然后使用图片数组转成灰度数据,在调用zbar既可以识别。

不过移植后会有一个问题,不能重复调用识别二维码,很容易内存就崩了。为了解决这个问题,让这个zbar库可以真正的用起来,不得不找到问题所在。

这里直观的看就是内存问题,奈何如果从源码直接去查找malloc和free的匹配所需时间太大,只能动态调试查找原因,所以第一步,我移植了rt-thread系统,使用rt的内存管理api。

移植rt-thread很方便,现在stm32代码生成工具cubemx可以直接添加rt-thread库,所以移植rt-thread系统很快。具体如下图:

1573931-20230525142401684-1457167346.png

移植完rt-thread后,就需要把zbar库中用到的malloc、calloc、free等操作函数换成 rt-malloc、rt-calloc、rt-free等,直接用全局搜索和替换。

替换后打开rt的内存调试功能宏定义:在rtdebug.h文件中

1573931-20230525142707713-755621118.png

更改后既可以看到打印内存申请和释放日志,以下为日志打印内容

 通过对申请和释放的对应关系,我们可以分析得出问题所在,zbar库在图片识别后释放了img->data指针,而这个指针是在zbar调用外部申请的空间,是不需要zbar内部释放的,具体代码如下:

int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t test[]="start test\n";
uint16_t i,j;
int qr_img_width = 240;
uint16_t Color;
uint16_t cnt = 0;
unsigned char *pic_rgb = (unsigned char *)gImage_test;
unsigned char *pic_hd = NULL;
unsigned char *pic_data = NULL;
void * ptr_start;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
//HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
//SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_ETH_Init();
MX_ICACHE_Init();
MX_LPUART1_UART_Init();
//MX_USART3_UART_Init();
MX_UCPD1_Init();
MX_USB_PCD_Init();
/* USER CODE BEGIN 2 */
pic_data = rt_malloc(qr_img_width*qr_img_width);
if(pic_data == NULL)
{
printf("malloc error\n");
return 0;
}
else
{
printf("pic_data:0x%x\n",pic_data);
}
//memset(pic_data,0,qr_img_width*qr_img_width);
pic_hd = pic_data;
for(i=0;i<qr_img_width;i++)
{
for(j=0;j<qr_img_width;j++)      //将RGB565图片转成灰度
{
Color = (*pic_rgb) | (*(pic_rgb+1)<<8);
*pic_hd = (((Color&0xF800)>> 8)*77+((Color&0x7E0)>>3)*150+((Color&0x001F)<<3)*29)/256;
pic_hd++;
pic_rgb++;
pic_rgb++;
}
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if( Zbar_Test((void* )pic_data,qr_img_width,qr_img_width) == 0 )
{
printf("zbar failed \n");
//rt_free(pic_data);
}
else
{
cnt ++;
printf("zbar ok \n");
//rt_free(pic_data);
}
printf("zbar count;%d\n",cnt);
//list_thread();
rt_thread_mdelay(5000);
}
rt_free(pic_data);
/* USER CODE END 3 */
}

  即pic_data灰度图片数据是不需要zbar释放的,但是zbar库中做了释放操作,代码如下:

inline void zbar_image_rt_free_data (zbar_image_t *img)
{
if(!img)
return;
if(img->src) {
/* replace video image w/new copy */
assert(img->refcnt); /* FIXME needs lock */
zbar_image_t *newimg = zbar_image_create();
memcpy(newimg, img, sizeof(zbar_image_t));
/* recycle video image */
newimg->cleanup(newimg);
/* detach old image from src */
img->cleanup = NULL;
img->src = NULL;
img->srcidx = -1;
}
else if(img->cleanup && img->data) {
if(img->cleanup != zbar_image_rt_free_data) {
/* using function address to detect this case is a bad idea;
* windows link libraries add an extra layer of indirection...
* this works around that problem (bug #2796277)
*/
zbar_image_cleanup_handler_t *cleanup = img->cleanup;
img->cleanup = zbar_image_rt_free_data;
cleanup(img);
}
//传入图片为外部指针,zbar内部不用free此指针
//        else
//            rt_free((void*)img->data);
}
img->data = NULL;
}

  这里把这一句屏蔽,则可以解决问题,经过我测试,现在已经连续运行上千次

decoded QR-Code symbol "EEWorld STM32H5"
len = 15
45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
zbar count;4290
n = 1
decoded QR-Code symbol "EEWorld STM32H5"
len = 15
45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
zbar count;4291
n = 1
decoded QR-Code symbol "EEWorld STM32H5"
len = 15
45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
zbar count;4292
n = 1
decoded QR-Code symbol "EEWorld STM32H5"
len = 15
45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
zbar count;4293
n = 1
decoded QR-Code symbol "EEWorld STM32H5"
len = 15
45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok
zbar count;4294

 工程文件下载:http://bbs.eeworld.com.cn/thread-1244434-1-1.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK