-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
916 lines (553 loc) · 44.3 KB
/
index.html
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge" >
<link rel="dns-prefetch" href="http://muddog.github.io">
<title>MudDog</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="Linux & IoT">
<meta property="og:type" content="website">
<meta property="og:title" content="MudDog">
<meta property="og:url" content="http://muddog.github.io/index.html">
<meta property="og:site_name" content="MudDog">
<meta property="og:description" content="Linux & IoT">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="MudDog">
<meta name="twitter:description" content="Linux & IoT">
<link rel="alternative" href="/atom.xml" title="MudDog" type="application/atom+xml">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="/main.css">
</head>
<body>
<div id="container">
<div class="left-col">
<div class="overlay"></div>
<div class="intrude-less">
<header id="header" class="inner">
<a href="/" class="profilepic">
<img src="/avatar.png" class="js-avatar">
</a>
<hgroup>
<h1 class="header-author"><a href="/">豆芽</a></h1>
</hgroup>
<nav class="header-menu">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/tags/IoT">IoT</a></li>
<li><a href="/tags/embeded">Embeded</a></li>
<li><a href="/tags/photo">Photograph</a></li>
</ul>
</nav>
<nav class="header-smart-menu">
<a class="js-smart-menu" data-idx="0" href="javascript:void(0)">所有文章</a>
<a class="js-smart-menu" data-idx="1" href="javascript:void(0)">标签</a>
<a class="js-smart-menu" data-idx="2" href="javascript:void(0)">关于我</a>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="https://github.com/muddog" title="github">github</a>
<a class="weibo" target="_blank" href="http://weibo.com/muddogxp/" title="weibo">weibo</a>
<a class="zhihu" target="_blank" href="https://www.zhihu.com/people/muddog" title="zhihu">zhihu</a>
<a class="linkedin" target="_blank" href="http://www.linkedin.com/in/xinyu-chen-eric" title="linkedin">linkedin</a>
</div>
</nav>
</header>
</div>
</div>
<div class="mid-col">
<nav id="mobile-nav">
<div class="overlay">
<div class="slider-trigger"><i class="icon-list"></i></div>
<h1 class="header-author js-mobile-header hide">豆芽</h1>
</div>
<div class="intrude-less">
<header id="header" class="inner">
<div class="profilepic">
<img src="/avatar.png" class="js-avatar">
</div>
<hgroup>
<h1 class="header-author">豆芽</h1>
</hgroup>
<nav class="header-menu">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/tags/IoT">IoT</a></li>
<li><a href="/tags/embeded">Embeded</a></li>
<li><a href="/tags/photo">Photograph</a></li>
</ul>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="https://github.com/muddog" title="github">github</a>
<a class="weibo" target="_blank" href="http://weibo.com/muddogxp/" title="weibo">weibo</a>
<a class="zhihu" target="_blank" href="https://www.zhihu.com/people/muddog" title="zhihu">zhihu</a>
<a class="linkedin" target="_blank" href="http://www.linkedin.com/in/xinyu-chen-eric" title="linkedin">linkedin</a>
</div>
</nav>
</header>
</div>
</nav>
<div class="body-wrap">
<article id="post-QRScanner-QT" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/03/02/QRScanner-QT/">QT二维码扫码应用(i.MX6UL)</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h1><p>去年年底还在裸写寄存器编程,今年就开始回归到Linux,还玩起了QT。这个跨度真是大啊。第一任务是在i.MX6UL/ULL上用Yocto做一个参考的带QT开发环境的镜像,并且在该环境下写个二维码扫码应用。虽然一开始接触Yocto,还是蛮陌生的,花了点时间,中间关于QCamera的支持上还绕了点弯路。但总算顺利搞定。</p>
<p>i.MX6UL属于i.MX系列中相对低端的AP,528Mhz的主频(6ULL会有1GHz),摄像头接口,2D硬件加速(例如CSC/FLIP/ROTATION),并且带有LCD显示。可以广泛应用于工业市场,特别是工控HMI,做简单的人机界面。HMI不需要3D渲染加速,但需要有一个能够简单上手的GUI开发环境,所以Linux + QT相当的适合。并且随着线上、线下互动的增强,移动支付,产线物流物品的追溯和管理,二维码扫码的应用也使用的越来越广泛。所以QT加上一个二维码扫码的应用对于在工业市场上的推广比较有利。</p>
<p>之前的博文也提到了如何去搭建一个完整的QT开发环境,以及ROOTFS。也可以参见这里:<a href="https://community.nxp.com/docs/DOC-333580" target="_blank" rel="external">https://community.nxp.com/docs/DOC-333580</a></p>
<h1 id="开源代码"><a href="#开源代码" class="headerlink" title="开源代码"></a>开源代码</h1><p>目前的这个二维码扫码应用程序(QRScanner),是基于QT5.6 + QZXing开发的,可以跑在i.MX6UL EVK板子上。测试用的是UVC的摄像头(640x480分辨率),480x272的标配LCD。</p>
<p>代码开源在我的Github上:<a href="https://github.com/muddog/QRScanner" target="_blank" rel="external">https://github.com/muddog/QRScanner</a> </p>
<h1 id="截图"><a href="#截图" class="headerlink" title="截图"></a>截图</h1><p><img src="https://community.nxp.com/servlet/JiveServlet/downloadImage/102-333910-1-177984/screenshot-qrscanner.png" alt=""></p>
<h1 id="应用的实现"><a href="#应用的实现" class="headerlink" title="应用的实现"></a>应用的实现</h1><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>做这种多媒体的应用,特别是和摄像头、视频显示相关的,你肯定会第一个想到使用Gstreamer。没错!其实一个简单的命令就可以验证你的思路。例如在6UL上做摄像头的预览(viewfinder),并且用PXP做YUV->RGB的转换,及Scale:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ gst-launch-1.0 v4l2src device=/dev/video1 ! video/x-raw,format=YUY2,width=640,height=320 ! imxvideoconvert_pxp ! video/x-raw,format=RGB16 ! waylandsink</div></pre></td></tr></table></figure></p>
<p>CPU的loading大概在20-30%,但如果不用PXP做加速,那么loading大概在50-60%。所以肯定需要加速啦。但还有个问题,既然我们用了QT,QT是否有可以直接用的组件呢?查了下Qtmultimedia,有个QCamera类,底下的实现在Linux上是基于Gstreamer的,看似很美好啊,我们可以直接用QCamera么?答案是可以,但性能太差,待会儿会讲到。所以绕了这个弯路后,终于回到了原点,还是老老实实利用GStreamer的API来实现吧。Appsink可以将获取的摄像头桢数据传给应用程序,所以,我们的目标就是建立类似上面的pipeline,并把waylandsink替换成appsink。</p>
<h2 id="代码分析"><a href="#代码分析" class="headerlink" title="代码分析"></a>代码分析</h2><p>代码很简单,实现几个类:<br>-<strong>ScannerQWidgetSink</strong><br>利用Gst appsink实现一个做视频预览的sink。初始化Gstreamer pipeline,创建一个定时器,每隔一段时间(50ms)将从摄像头获取的桢,用appsink API拷贝到内部的buffer,并且通知做预览的Widget更新界面(ViewfinderWidget redraw)</p>
<p>-<strong>ViewfinderWidget</strong><br>继承自QWidget,实现将appsink取来的桢打包成一个QImage实例,并且使用QPainter画到自己的surface上。</p>
<p>-<strong>MainWindow</strong><br>主界面类,没有边框和标题栏,全屏。在界面左半边实例化了ViewfinderWidget,右边实例化一个QLabel来显示扫码结果。并且利用动画在预览Widget上绘制红色扫码线动画。</p>
<p>-<strong>DecoderThread</strong><br>独立线程。等待ScannerQWidgetSink每0.5s释放一帧图像资源,然后将该数据拷贝到自己的buffer里,送给QZXing引擎做二维码解析。最后将结果显示在QLabel实例上。</p>
<h2 id="为什么不用QCamera"><a href="#为什么不用QCamera" class="headerlink" title="为什么不用QCamera"></a>为什么不用QCamera</h2><p>QCamera用的是Gstreamer bad plugins里的camerabin2,这个BIN消耗的资源特别大,对于Preview,Image Capture,Video Recording各有三套不同的pipeline,还有一波proxy PAD,而且PAD都用的是纯软件的。光pipeline negoation就要花半天,更别说跑起来的速度,在没有PXP的加速下Preview CPU就要耗掉60-70%。我试图在Camerabin2的viewfinder pipeline里用imxvideoconvert_pxp替代videoconvert来加速CSC, Scale,但是始终会出错整个pipeline停止。这个问题找了我将近1个多礼拜。后来发现Qtmultimedia在处理非xcb的platform时候,不会用到Gstreamer内的sink来做显示加速。而使用自己写的qgstvideorendersink类来实现sink,可该sink有bug,会和需要render的widget不同步,导致自己报错。找了个workaround后,CPU loading降了下来,但后面image capture问题又来了,取一帧数据速度实在太慢,好几秒,根本无法接受。所以干脆放弃,还是直接自己建gst pipeline得了。</p>
</div>
<div class="article-info article-info-index">
<a href="/2017/03/02/QRScanner-QT/" class="archive-article-date">
<time datetime="2017-03-02T14:22:30.921Z" itemprop="datePublished"><i class="icon-clock"></i>2017-03-02</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Gstreamer/">Gstreamer</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Linux/">Linux</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/QT/">QT</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Krabi-Trip" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/02/05/Krabi-Trip/">在Krabi过春节</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="第二次出国旅行,在这个年味减淡的春节"><a href="#第二次出国旅行,在这个年味减淡的春节" class="headerlink" title="第二次出国旅行,在这个年味减淡的春节"></a>第二次出国旅行,在这个年味减淡的春节</h2><h3 id="Krabi甲米"><a href="#Krabi甲米" class="headerlink" title="Krabi甲米"></a>Krabi甲米</h3><p>第一次开启如此温暖的春节过节模式</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4806.jpg" width="960">
<p>在机场也有过年气氛</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4766.jpg" width="480">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4791.jpg" width="480">
<p>飞机!这次见到飞机要比上次去日本兴奋很多</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4750.jpg" width="960">
<p>在海滩上玩的好HIGH</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4830.jpg" width="960">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4833.jpg" width="960">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4837.jpg" width="960">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4927.jpg" width="960">
<p><br><br><img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4981.jpg" width="480"><br><img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_4995.jpg" width="480"></p>
<p>第一次近距离接触小猴子</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_5027.jpg" width="480">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_5035.jpg" width="480">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_5040.jpg" width="480">
<img src="http://ohx9w4r3g.bkt.clouddn.com/201701/Krabi/DSC_5042.jpg" width="480">
<h3 id="一切的体验,都是你成长路上的伙伴"><a href="#一切的体验,都是你成长路上的伙伴" class="headerlink" title="一切的体验,都是你成长路上的伙伴"></a>一切的体验,都是你成长路上的伙伴</h3>
</div>
<div class="article-info article-info-index">
<a href="/2017/02/05/Krabi-Trip/" class="archive-article-date">
<time datetime="2017-02-05T13:46:12.915Z" itemprop="datePublished"><i class="icon-clock"></i>2017-02-05</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Family/">Family</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Krabi/">Krabi</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Photography/">Photography</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-QT-On-Yocto" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/01/02/QT-On-Yocto/">Enable QT developement for i.MX6UL</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>Qt is a cross-platform application framework that is widely used for developing application software that can be run on various software and hardware platforms with little or no change in the underlying codebase, while still being a native application with native capabilities and speed. It is running in TV, Car, HMI, 3D Printer, almost covering all of the embedded areas. This document introduces how to setup the development environment to build Qt application, deploy to NXP’s i.MX6UL EVK board, and run application on the Linux BSP.</p>
<h2 id="Hardware-Requirement"><a href="#Hardware-Requirement" class="headerlink" title="Hardware Requirement"></a>Hardware Requirement</h2><ul>
<li>PC Host: x86_64 Ubuntu-16.10</li>
<li>Target: i.mx6ul 14x14 EVK with LCD pannel</li>
<li>Mico-SD card</li>
<li>Ethernet cable & USB cable for console & Power adapter</li>
</ul>
<h2 id="QT-SDK"><a href="#QT-SDK" class="headerlink" title="QT SDK"></a>QT SDK</h2><p>QT one ecosystem provide SDK to build powerful, connected and beautiful applications that run on any screen and across any platform. Here for embedded development, we need the following tools:</p>
<ol>
<li>Qt Creator IDE</li>
<li>Qt5.6 source code</li>
<li>HOST build toolchain</li>
<li>TARGET build toolchain
<p class="article-more-link">
<a class="article-more-a" href="/2017/01/02/QT-On-Yocto/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2017/01/02/QT-On-Yocto/" class="archive-article-date">
<time datetime="2017-01-02T05:18:44.405Z" itemprop="datePublished"><i class="icon-clock"></i>2017-01-02</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Linux/">Linux</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/QT/">QT</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Yocto/">Yocto</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/i-MX6/">i.MX6</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Dog-Nanny" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/12/24/Dog-Nanny/">找回豆芽保姆</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>找回了几年前做的“豆芽保姆”,原来它安静的躺在Google Code上。早当年用github都好。果断将它搬家到github: <a href="https://github.com/muddog/dognanny" target="_blank" rel="external">https://github.com/muddog/dognanny</a></p>
<h2 id="接口微博"><a href="#接口微博" class="headerlink" title="接口微博"></a>接口微博</h2><p><a href="http://weibo.com/u/3211753593?refer_flag=1005055013_&is_all=1" target="_blank" rel="external">@豆芽保姆</a></p>
<h2 id="硬件平台"><a href="#硬件平台" class="headerlink" title="硬件平台"></a>硬件平台</h2><p>i.MX6D的开发板 + Temper1 USB温度传感器 + UVC摄像头 + USB红外控制器<br><img src="http://ww2.sinaimg.cn/mw690/62c2bccfjw1e1lzyl3xk6j.jpg" width="640"></p>
<h2 id="软件"><a href="#软件" class="headerlink" title="软件"></a>软件</h2><p>Ubuntu + Python + C</p>
<h2 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h2><p>在微博上找@豆芽保姆</p>
</div>
<div class="article-info article-info-index">
<a href="/2016/12/24/Dog-Nanny/" class="archive-article-date">
<time datetime="2016-12-24T14:28:00.366Z" itemprop="datePublished"><i class="icon-clock"></i>2016-12-24</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/IoT/">IoT</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Linux/">Linux</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Python/">Python</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/豆芽保姆/">豆芽保姆</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Sunshine-Hangzhou" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/12/10/Sunshine-Hangzhou/">枫叶红了...你慢慢长大</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h3 id="不在乎你今后是否记得,不在乎我们是否疲惫。出发,在旅途上的体验即使你的成长。。"><a href="#不在乎你今后是否记得,不在乎我们是否疲惫。出发,在旅途上的体验即使你的成长。。" class="headerlink" title="不在乎你今后是否记得,不在乎我们是否疲惫。出发,在旅途上的体验即使你的成长。。"></a>不在乎你今后是否记得,不在乎我们是否疲惫。出发,在旅途上的体验即使你的成长。。</h3><p>杭州之行。。。</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/hangzhou1612/DSC_4119.jpg" width="640">
<p>你在寺庙里攀爬,看到了信徒们的虔诚</p>
<img src="http://ohx9w4r3g.bkt.clouddn.com/hangzhou1612/DSC_4156.jpg" width="640">
<p class="article-more-link">
<a class="article-more-a" href="/2016/12/10/Sunshine-Hangzhou/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2016/12/10/Sunshine-Hangzhou/" class="archive-article-date">
<time datetime="2016-12-10T14:06:13.403Z" itemprop="datePublished"><i class="icon-clock"></i>2016-12-10</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Family/">Family</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Hangzhou/">Hangzhou</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Photography/">Photography</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Play-With-mbedOS" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/11/25/Play-With-mbedOS/">玩转mbedOS</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>mbedOS是ARM自己打造、主打IoT的一整套软件解决方案,是一个针对ARM CortexM系列处理器的嵌入式开源生态。详细的一些介绍可以参见我的另一篇文章<a href="http://muddog.pub/2016/11/12/IoT-RTOS/">《IoT的那些操作系统》</a><br>从日常的工作、及和其他支持部门的交流来看,mbedOS现在还处于成长和推广阶段,在国内正真使用的客户貌似还很少,国外确实有比较牛X的客户指名道姓需要NXP的硬件来支持mbedOS。本人还是比较看好mbed,毕竟亲爹是ARM,而且提供BLE,802.15.4,6LowPAN,Thread,驱动框架及RTOS等等丰富的软件解决方案。所以么,不要等客户培养起来了再去研究,早起的鸟儿有虫吃。</p>
<h1 id="搭建环境"><a href="#搭建环境" class="headerlink" title="搭建环境"></a>搭建环境</h1><h2 id="开发板"><a href="#开发板" class="headerlink" title="开发板"></a>开发板</h2><p>mbedOS的例子大部分都可以直接跑在NXP的FRDM-K64之上。</p>
<ul>
<li>mbed官方对板子的<a href="https://developer.mbed.org/platforms/FRDM-K64F/">介绍及使用方法</a>,</li>
<li>NXP官网对板子的<a href="http://www.nxp.com/products/software-and-tools/hardware-development-tools/freedom-development-boards/freedom-development-platform-for-kinetis-k64-k63-and-k24-mcus:FRDM-K64F?fsrch=1&sr=1&pageNum=1">介绍</a></li>
</ul>
<p>买板子,虽然mbed和NXP都可以买,但还是淘宝吧,发货快。</p>
<h2 id="开发工具"><a href="#开发工具" class="headerlink" title="开发工具"></a>开发工具</h2><p>mbedOS支持三种开发工具:<br>1.在线IDE<br>2.mbed CLI控制台<br>3.第三方开发工具,如IAR,MDK</p>
<p>在线IDE编译很方便快捷,但没有调试功能。第三方的IDE都是可视化的,也没啥好介绍的。这里着重会来介绍mbed-cli,它的作用贯穿于整个mbed工作流:代码仓库版本控制、依赖管理、代码发布、从其他地方获取代码、调用编译系统及其他。无论你是用Windows还是Linux的主机,先准备好安装这四个工具:</p>
<ul>
<li>Python - mbed CLI 是用Python写的,并且在 version 2.7.11 上做过完整测试,不兼容Python3.x.</li>
<li><a href="https://git-scm.com/">Git</a> - version 1.9.5 or later</li>
<li><a href="https://www.mercurial-scm.org/">Mercurial</a> - version 2.2.2 or later</li>
<li><a href="https://launchpad.net/gcc-arm-embedded">GNU ARM</a> - ARM GCC交叉编译工具</li>
</ul>
<p class="article-more-link">
<a class="article-more-a" href="/2016/11/25/Play-With-mbedOS/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2016/11/25/Play-With-mbedOS/" class="archive-article-date">
<time datetime="2016-11-25T12:54:39.490Z" itemprop="datePublished"><i class="icon-clock"></i>2016-11-25</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/IoT/">IoT</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/RTOS/">RTOS</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mbed/">mbed</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mbedOS/">mbedOS</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-DTLS-Analysis" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/11/20/DTLS-Analysis/">借助mbedTLS了解DTLS握手协议</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h2><p>本文将会利用mbedTLS协议栈,通过dump协议栈调试信息,抓包,代码分析等方式来对DTLS的握手协议进行介绍。</p>
<h2 id="DTLS简介"><a href="#DTLS简介" class="headerlink" title="DTLS简介"></a>DTLS简介</h2><p>简单说,DTLS(Datagram Transport Layer Security)实现了在UDP协议之上的TLS安全层。由于基于TCP的SSL/TLS没有办法处理UDP报文的丢包及重排序(这些问题一般交给UDP的上层应用解决),DTLS在原本TLS的基础上做了一些小改动(复用大部分TLS的代码)来解决如下UDP上实现TLS的问题:</p>
<ol>
<li>TLS记录层内记录的强关联性及无序号</li>
<li>握手协议的可靠性<ul>
<li>包丢失重传机制(UDP无重传机制)</li>
<li>无法按序接收(握手需要对包按顺序处理,而UDP包的到达并非按序,包头没有TCP那样的Seq/Ack number)</li>
<li>握手协议包长(证书之类传输可能达到KB级别)导致的UDP分包组包(类似于UDP在IP层的分包)</li>
</ul>
</li>
<li>重复包(Replay)检测</li>
</ol>
<p>由于UDP/DTLS相较于TCP/TLS的轻量化及较小的开销,目前被更多的运用的嵌入式环境中。例如CoAP使用DTLS来实现安全通路,CoAP及其上层的LWM2M则运用在物联网和云端的通讯上。</p>
<p>如果你已经很熟悉TLS,那么看到这里后就请忽略此文:)</p>
<h2 id="如何借助mbedTLS来分析握手协议"><a href="#如何借助mbedTLS来分析握手协议" class="headerlink" title="如何借助mbedTLS来分析握手协议"></a>如何借助mbedTLS来分析握手协议</h2><p>mbedTLS(前身PolarSSL)是面向嵌入式系统,实现的一套易用的加解密算法和SSL/TLS库。mbedTLS系统开销极小,对于系统资源要求不高。mbedTLS是开源项目,并且使用Apache 2.0许可证,使得用户既可以讲mbedTLS使用在开源项目中,也可以应用于商业项目。目前使用mbedTLS的项目很多,例如Monkey HTTP Daemon,LinkSYS路由器。</p>
<p>我们在这里简单的利用mbedTLS自带的dtls_client/dtls_server的测试程序来分析握手协议。这里要说明的是mbedTLS这个自带的DTLS 测试程序,服务器只在localhost做bind,客户端也只连接到localhost。实际上是个loopback测试。并且使用了TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384的Cipher Suite,也就是用椭圆曲线(EC)的DH算法来实现密钥(Session Key)的协商,用RSA来实现密钥协商时交换的EC类型,DH公钥等数据的签名加密。所以握手的流程和其他一些加密方式会有所差别。比如和单纯的RSA密钥交换方式比起来,会多一个<strong>“Server Key Exchange”</strong>报文。</p>
<h3 id="下载mbedTLS"><a href="#下载mbedTLS" class="headerlink" title="下载mbedTLS"></a>下载mbedTLS</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="variable">$git</span> <span class="built_in">clone</span> https://github.com/ARMmbed/mbedtls</div></pre></td></tr></table></figure>
<p class="article-more-link">
<a class="article-more-a" href="/2016/11/20/DTLS-Analysis/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2016/11/20/DTLS-Analysis/" class="archive-article-date">
<time datetime="2016-11-20T14:30:07.031Z" itemprop="datePublished"><i class="icon-clock"></i>2016-11-20</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/DTLS/">DTLS</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/handshake/">handshake</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mbedTLS/">mbedTLS</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-IoT-RTOS" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/11/12/IoT-RTOS/">IoT的那些操作系统</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h1><p>IoT(Internet of Things)一直是个市场没爆发,但炒作够火的概念。 最近看了Brillo(Goolge放出的OS for IoT),再结合手头做的项目,来聊聊打着IoT旗号的那些操作系统及其生态。可以让大家在对此类嵌入式系统软件平台选型时少些困惑。</p>
<p>首先,不在这里描述IoT到底是啥,这概念太笼统。但凡事都讲套路,在我看来大部分的IoT操作系统都是顺着这个套路(应用场景)来:</p>
<pre><code> Internet PAN
Cloud <-> Board router <-> Nodes (things connected)
^ ^ ^
| | |
---- Smart device ------
(e.g. phone, tablet)
</code></pre><p>这场景基本适用于家庭、楼宇及工业等等。所以哪家提啥方案都可以按这个套路来,下面你会看的到。文中我们会谈到以下这些OS:</p>
<ul>
<li>Brillo (a solution from Google for building connected devices)</li>
<li>mbedOS (ARM mbed, The ARM IoT Device Platform)</li>
<li>RIOT (The friendly Operating System for the IoT)</li>
<li>Contiki (an open source operating system for the IoT)</li>
<li>Zephyr (a small, scalable real-time operating system for use on resource-constrained systems)</li>
<li>Nuttx (a RTOS with an emphasis on standards compliance and small footprint)</li>
</ul>
<p>除了单独对这些OS介绍外,我们也会来个横向大比拼。目的是让项目负责人,产品经理在对系统选型的时候能有个合理的参考。嵌入式系统中,最好用,生态最好的当然是Linux。但当系统较小,能力不足以跑Linux的时候,就很容易纠结,特别是对于生态要求很高的应用。</p>
<h1 id="Brillo"><a href="#Brillo" class="headerlink" title="Brillo"></a>Brillo</h1><p><a href="https://developers.google.com/brillo/">https://developers.google.com/brillo/</a></p>
<blockquote>
<p>Brillo: Google’s OS for IoT MPU devices<br>• Targeted at smart homes<br>• Expanding to buildings and industry<br>• Supports MPU devices w/ min 35MB of RAM</p>
</blockquote>
<p>Brillo需要跑在带MMU的AP上。其实很显然,Brillo基于Android,它再怎么裁剪,也是需要跑在Linux,Kernel上还要打一堆patch。只是它把Android上关于图形、JAVA虚拟机及Framework统统裁减掉。只保留了C/C++运行环境,Binder IPC,SSL等网络安全必须组件。这也就意味着在Brillo上开发APP其实是Native的,而且驱动程序都由Android的那套HAL来做抽象,所以应用程序是直接和HAL、Lib来打交道。</p>
<p class="article-more-link">
<a class="article-more-a" href="/2016/11/12/IoT-RTOS/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2016/11/12/IoT-RTOS/" class="archive-article-date">
<time datetime="2016-11-12T05:12:34.947Z" itemprop="datePublished"><i class="icon-clock"></i>2016-11-12</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Embeded/">Embeded</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/IoT/">IoT</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/RTOS/">RTOS</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Android-Recovery" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2009/04/25/Android-Recovery/">Android Recovery模式</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="Recovery简介"><a href="#Recovery简介" class="headerlink" title="Recovery简介"></a>Recovery简介</h2><p>Android利用Recovery模式,进行恢复出厂设置,OTA升级,patch升级及firmware升级。升级一般通过运行升级包中的META-INF/com/google/android/update-script脚本来执行自定义升级,脚本中是一组recovery系统能识别的UI控制,文件系统操作命令,例如write_raw_image(写FLASH分区),copy_dir(复制目录)。该包一般被下载至SDCARD和CACHE分区下。如果对该包内容感兴趣,可以从<a href="http://forum.xda-developers.com/showthread.php?t=442480">http://forum.xda-developers.com/showthread.php?t=442480</a> 下载JF升级包来看看。升级中还涉及到包的数字签名,签名方式和普通JAR文件签名差不错。公钥会被硬编译入recovery,编译时生成在:out/target/product/XX/obj/PACKAGING/ota_keys_inc_intermediates/keys.inc</p>
<h3 id="G1中的三种启动模式"><a href="#G1中的三种启动模式" class="headerlink" title="G1中的三种启动模式"></a>G1中的三种启动模式</h3><p>MAGIC KEY:</p>
<ol>
<li>camera + power:bootloader模式,ADP里则可以使用fastboot模式</li>
<li>home + power:recovery模式</li>
<li>正常启动, Bootloader正常启动,又有三种方式,按照BCB(Bootloader Control Block, 下节介绍)中的command分类:<ul>
<li>command == ‘boot-recovery’ → 启动recovery.img。recovery模式</li>
<li>command == ‘update-radio/hboot’ → 更新firmware(bootloader)</li>
</ul>
</li>
<li>其他 → 启动boot.img</li>
</ol>
<p class="article-more-link">
<a class="article-more-a" href="/2009/04/25/Android-Recovery/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2009/04/25/Android-Recovery/" class="archive-article-date">
<time datetime="2009-04-25T05:00:00.000Z" itemprop="datePublished"><i class="icon-clock"></i>2009-04-25</time>
</a>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-Hrtimer-Clockevent-Timekeeping" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2007/11/14/Hrtimer-Clockevent-Timekeeping/">Linux Kernel Timekeeping</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>kernel-2.6.22中的arm arch加入了对dynticks, clocksource/event支持. imx31的BSP在clock这里有一些改动. 找了些kernel clock及timer子系统近来的变化, 总结一下。<br>一般来说Soft-Timer (timer wheel / hrtimer) 都是由Hardware-Timer(时钟中断之类)以及相关的clock source(e.g GPT in Soc)驱动, 所以我打算先从clock这层开始介绍, 接着是soft-timer, kernel timekeeping, 最后来看一些应用.</p>
<p class="article-more-link">
<a class="article-more-a" href="/2007/11/14/Hrtimer-Clockevent-Timekeeping/#more">more >></a>
</p>
</div>
<div class="article-info article-info-index">
<a href="/2007/11/14/Hrtimer-Clockevent-Timekeeping/" class="archive-article-date">
<time datetime="2007-11-14T05:00:00.000Z" itemprop="datePublished"><i class="icon-clock"></i>2007-11-14</time>
</a>
<div class="article-tag tagcloud">
<i class="icon-price-tags"></i>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Clocksource/">Clocksource</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/HRTimer/">HRTimer</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Kernel/">Kernel</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Linux/">Linux</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Timekeeping/">Timekeeping</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<nav id="page-nav">
<span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="extend next" rel="next" href="/page/2/">Next »</a>
</nav>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info">
<div class="footer-left">
© 2017 豆芽
</div>
<div class="footer-right">
<a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/litten/hexo-theme-yilia" target="_blank">Yilia</a> by Litten
</div>
</div>
</div>
</footer>
</div>
<script>
var yiliaConfig = {
fancybox: true,
mathjax: false,
animate: true,
isHome: true,
isPost: false,
isArchive: false,
isTag: false,
isCategory: false,
open_in_new: false,
root: "/",
innerArchive: true
}
</script>
<script src="/./main.js"></script>
<div class="tools-col">
<ul class="btn-wrap">
<li class="chose" data-hook="tools-section-all"><span class="text">全部</span><i class="icon-book"></i></li>
<li data-hook="tools-section-tag"><span class="text">标签</span><i class="icon-price-tags"></i></li>
<li data-hook="tools-section-me"><span class="text">我</span><i class="icon-smile"></i></li>
</ul>
<div class="tools-wrap">
<section class="tools-section tools-section-all chose">
</section>
<section class="tools-section tools-section-tag">
<div class="widget tagcloud" id="js-tagcloud">
<a href="/tags/Blocking/" style="font-size: 10px;">Blocking</a> <a href="/tags/Cache/" style="font-size: 10px;">Cache</a> <a href="/tags/Clocksource/" style="font-size: 10px;">Clocksource</a> <a href="/tags/DTLS/" style="font-size: 10px;">DTLS</a> <a href="/tags/Embeded/" style="font-size: 10px;">Embeded</a> <a href="/tags/FTP/" style="font-size: 10px;">FTP</a> <a href="/tags/Family/" style="font-size: 12.5px;">Family</a> <a href="/tags/Gstreamer/" style="font-size: 10px;">Gstreamer</a> <a href="/tags/HRTimer/" style="font-size: 10px;">HRTimer</a> <a href="/tags/Hangzhou/" style="font-size: 10px;">Hangzhou</a> <a href="/tags/IoT/" style="font-size: 15px;">IoT</a> <a href="/tags/Kernel/" style="font-size: 17.5px;">Kernel</a> <a href="/tags/Krabi/" style="font-size: 10px;">Krabi</a> <a href="/tags/Linux/" style="font-size: 20px;">Linux</a> <a href="/tags/Memory/" style="font-size: 10px;">Memory</a> <a href="/tags/Netfilter/" style="font-size: 12.5px;">Netfilter</a> <a href="/tags/Photography/" style="font-size: 12.5px;">Photography</a> <a href="/tags/Python/" style="font-size: 10px;">Python</a> <a href="/tags/QT/" style="font-size: 12.5px;">QT</a> <a href="/tags/RTOS/" style="font-size: 12.5px;">RTOS</a> <a href="/tags/TCP/" style="font-size: 10px;">TCP</a> <a href="/tags/Thread/" style="font-size: 12.5px;">Thread</a> <a href="/tags/Timekeeping/" style="font-size: 10px;">Timekeeping</a> <a href="/tags/Yocto/" style="font-size: 10px;">Yocto</a> <a href="/tags/buddy/" style="font-size: 10px;">buddy</a> <a href="/tags/handshake/" style="font-size: 10px;">handshake</a> <a href="/tags/i-MX6/" style="font-size: 10px;">i.MX6</a> <a href="/tags/mbed/" style="font-size: 10px;">mbed</a> <a href="/tags/mbedOS/" style="font-size: 10px;">mbedOS</a> <a href="/tags/mbedTLS/" style="font-size: 10px;">mbedTLS</a> <a href="/tags/豆芽保姆/" style="font-size: 10px;">豆芽保姆</a>
</div>
</section>
<section class="tools-section tools-section-me">
<div class="aboutme-wrap" id="js-aboutme">土狗一只<br><br>码农<br>嵌入式</div>
</section>
</div>
</div>
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>