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系统很快。具体如下图:
移植完rt-thread后,就需要把zbar库中用到的malloc、calloc、free等操作函数换成 rt-malloc、rt-calloc、rt-free等,直接用全局搜索和替换。
替换后打开rt的内存调试功能宏定义:在rtdebug.h文件中
更改后既可以看到打印内存申请和释放日志,以下为日志打印内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | malloc size 156 allocate memory at 0x2001008c, size: 168 malloc size 296 allocate memory at 0x20010134, size: 308 malloc size 32 allocate memory at 0x20010268, size: 44 malloc size 48 allocate memory at 0x20010294, size: 60 malloc size 2856 allocate memory at 0x200102d0, size: 2868 malloc size 52 allocate memory at 0x20010e04, size: 64 allocate memory at 0x20010e04, size: 64 malloc size 16 allocate memory at 0x20010e44, size: 28 malloc size 20 allocate memory at 0x20011388, size: 32 malloc size 60 allocate memory at 0x200113a8, size: 72 release memory 0x20011388, size: 32 malloc size 140 allocate memory at 0x200113f0, size: 152 release memory 0x200113a8, size: 72 malloc size 300 allocate memory at 0x20011488, size: 312 release memory 0x200113f0, size: 152 malloc size 620 allocate memory at 0x200115c0, size: 632 release memory 0x20011488, size: 312 malloc size 1260 allocate memory at 0x20011838, size: 1272 release memory 0x200115c0, size: 632 malloc size 2540 allocate memory at 0x20011d30, size: 2552 release memory 0x20011838, size: 1272 malloc size 20 allocate memory at 0x20011388, size: 32 malloc size 60 allocate memory at 0x200113a8, size: 72 release memory 0x20011388, size: 32 malloc size 140 allocate memory at 0x200113f0, size: 152 release memory 0x200113a8, size: 72 malloc size 300 allocate memory at 0x20011488, size: 312 release memory 0x200113f0, size: 152 malloc size 620 allocate memory at 0x200115c0, size: 632 release memory 0x20011488, size: 312 malloc size 1260 allocate memory at 0x20011838, size: 1272 release memory 0x200115c0, size: 632 malloc size 2540 allocate memory at 0x20012728, size: 2552 release memory 0x20011838, size: 1272 malloc size 352 allocate memory at 0x20011388, size: 364 malloc size 352 allocate memory at 0x200114f4, size: 364 malloc size 88 allocate memory at 0x20011660, size: 100 release memory 0x20011660, size: 100 malloc size 440 allocate memory at 0x20011660, size: 452 malloc size 440 allocate memory at 0x20011824, size: 452 malloc size 110, but align to 112 allocate memory at 0x200119e8, size: 124 release memory 0x200119e8, size: 124 malloc size 5792 allocate memory at 0x20013120, size: 5804 malloc size 80 allocate memory at 0x200119e8, size: 92 malloc size 20 allocate memory at 0x20011a44, size: 32 malloc size 32 allocate memory at 0x20011a64, size: 44 malloc size 5, but align to 8 allocate memory at 0x20011a90, size: 24 malloc size 8 allocate memory at 0x20011aa8, size: 24 release memory 0x20011aa8, size: 24 release memory 0x20011a90, size: 24 release memory 0x20011a64, size: 44 release memory 0x20011a44, size: 32 release memory 0x20011824, size: 452 release memory 0x20011660, size: 452 release memory 0x200114f4, size: 364 release memory 0x20011388, size: 364 malloc size 57600 allocate memory at 0x200147cc, size: 57612 malloc size 960 allocate memory at 0x20011388, size: 972 release memory 0x20011388, size: 972 malloc size 3, but align to 4 allocate memory at 0x20011388, size: 24 malloc size 360 allocate memory at 0x200113a0, size: 372 release memory 0x200113a0, size: 372 malloc size 360 allocate memory at 0x200113a0, size: 372 release memory 0x200113a0, size: 372 malloc size 176 allocate memory at 0x200113a0, size: 188 release memory 0x200113a0, size: 188 malloc size 176 allocate memory at 0x200113a0, size: 188 release memory 0x200113a0, size: 188 malloc size 552 allocate memory at 0x200113a0, size: 564 malloc size 552 allocate memory at 0x200115d4, size: 564 release memory 0x200113a0, size: 564 release memory 0x200115d4, size: 564 malloc size 52 allocate memory at 0x200113a0, size: 64 allocate memory at 0x200113a0, size: 64 malloc size 116 allocate memory at 0x200113e0, size: 128 malloc size 32 allocate memory at 0x20011460, size: 44 malloc size 32 allocate memory at 0x2001148c, size: 44 release memory 0x20011460, size: 44 release memory 0x2001148c, size: 44 malloc size 116 allocate memory at 0x20011460, size: 128 malloc size 8 allocate memory at 0x200114e0, size: 24 malloc size 70, but align to 72 allocate memory at 0x200114f8, size: 84 release memory 0x200113e0, size: 128 release memory 0x200113a0, size: 64 release memory 0x200114e0, size: 24 release memory 0x20011460, size: 128 malloc size 12 allocate memory at 0x200113a0, size: 24 malloc size 15, but align to 16 allocate memory at 0x200113b8, size: 28 release memory 0x200114f8, size: 84 malloc size 48 allocate memory at 0x200113d4, size: 60 release memory 0x20011388, size: 24 malloc size 4 allocate memory at 0x20011388, size: 24 malloc size 1, but align to 4 allocate memory at 0x20011410, size: 24 malloc size 31, but align to 32 allocate memory at 0x20011428, size: 44 malloc size 52 allocate memory at 0x20011454, size: 64 allocate memory at 0x20011454, size: 64 malloc size 8 allocate memory at 0x20011494, size: 24 malloc size 16 allocate memory at 0x200114ac, size: 28 release memory 0x20011494, size: 24 malloc size 24 allocate memory at 0x200114c8, size: 36 release memory 0x200114ac, size: 28 malloc size 32 allocate memory at 0x20011494, size: 52 release memory 0x200114c8, size: 36 malloc size 16 allocate memory at 0x200114c8, size: 28 release memory 0x20011428, size: 44 release memory 0x20011410, size: 24 release memory 0x200113b8, size: 28 release memory 0x200113a0, size: 24 release memory 0x200113d4, size: 60 release memory 0x200147cc, size: 57612 release memory 0x200119e8, size: 92 release memory 0x20013120, size: 5804 n = 1 decoded QR-Code symbol "EEWorld STM32H5" len = 15 release memory 0x20010e04, size: 64 release memory 0x20011494, size: 52 release memory 0x200114c8, size: 28 release memory 0x20011454, size: 64 release memory 0x20010e44, size: 28 release memory 0x20010294, size: 60 release memory 0x20010268, size: 44 release memory 0x20010134, size: 308 release memory 0x20011d30, size: 2552 release memory 0x20012728, size: 2552 release memory 0x200102d0, size: 2868 release memory 0x2001008c, size: 168 45 45 57 6F 72 6C 64 20 53 54 4D 33 32 48 35 zbar ok zbar count;56 |
通过对申请和释放的对应关系,我们可以分析得出问题所在,zbar库在图片识别后释放了img->data指针,而这个指针是在zbar调用外部申请的空间,是不需要zbar内部释放的,具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 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 { for (j=0;j { 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库中做了释放操作,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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; } |
这里把这一句屏蔽,则可以解决问题,经过我测试,现在已经连续运行上千次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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