又折腾网站迁移

终于把wordpress 的博客用hugo 转成静态网站放到github 了, 不过还很多细节要调整。 前段时间国内的域名空间备案被注销了,因为域名和空间不在同一家,真是无语。 之前是因为备案的那家空间续费太贵了,然后就把网站搬到另一家做活动的服务器上了。结果半年后就被警告备案的域名没有指向他家的服务器,要被注销。查了一下它家服务器还是贵,还让不让人活了。索性把网站做成纯静态的搬到github 上了。真是不容易。 也难怪这几年国内中文搜索的内容质量起来越差了。 这就有种像住出租房付不起房租,被赶来赶去的感觉。国内这一套真是被玩得越来越溜了。

域内的PC 访问非域内的samba服务器

加入某个域内的PC 在登录samba服务器的时候,默认会在USERNAME 前加上DOMAIN\, 所以一直登录失败。登陆窗口上也无法取消加 DOMAIN\。 解决方法: 控制面板->凭据管理器(Credential Manager) -> 手动添加Windows 凭据, 这样就可以用此用户账户正常登录了。

zynq 嵌入式开发总结

传统开发步骤 基础设计 # 使用Vidado 设计硬件工程,导出硬件设计 bitstream. $ File-> Export-> Export Hardware... # 使用SDK 生成 fsbl.elf # 编译U-boot $ make CROSS_COMPILE=arm-xilinx-linux-gnueabi- zynq_ac7020_defconfig # 使用SDK, Xilinx Tools->Create Boot Image 生成BOOT.BIN。 即: fsbl.elf + system_wrapper.bit + u-boot.elf 编译kernel $ make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- uImage LOADADDR=0x00008000 # 生成 /arch/arm/boot/uImage 编译device tree $ dtc -I dts -O dtb devicetree.dtb ./arch/arm/boot/dts/AC7020.dts 制作文件系统 $ 基于RAM 的 ramdisk $ 基于Flash 的 jffs2 $ 基于network 的 NFS 将 BOOT.bin, devicetree.dtb, uImage 拷贝至SD卡的FAT 分区。文件系统拷贝至ext 分区即可。

编译PYNQ 在ZCU102上的镜像

由于PYNQ官方没有编译好的ZCU102的镜像,所以需要自己手动编译。这里记录一下编译过程。 因为手头上的ZCU102 批次比较新,所以目前只能使用2018.3 版本的SDK才能BOOT起来。(应该是由于换了DDR型号了,所以老版本的镜像是BOOT不起来的。板子版本是REVISION 1.1的 新批号) PYNQ 版本Xilinx Tool 版本对应 Release version Xilinx Tool Version v1.4 2015.4 v2.0 2016.1 v2.1 2017.4 v2.2 2017.4 v2.3 2018.2 v2.4 2018.3 参考: https://blog.csdn.net/vacajk/article/details/84728062 https://github.com/Xilinx/PYNQ/tree/image_v2.4/sdbuild https://pynq.readthedocs.io/en/latest/pynq_sd_card.html#pynq-sd-card 准备工作 使用事先编译好的文件系统: bionic.aarch64.2.4.img ZCU102 BSP: xilinx-zcu102-v2018.3-final.bsp 如果非官方板子,比如黑金的AC7020, 没有BSP, 则可以从vivado 工程导出hdf 文件,给petalinux 生成一个bsp 安装好SDSoc2018.3, PetaLinux2018.3 系统环境 Ubuntu 1604-64 编译步骤 \# 下载 pynq $ git clone https://github.com/Xilinx/PYNQ.git $ cd PYNQ $ git checkout image\_v2.4 # 检查依赖环境,qemu,crosstool-ng $ cd .

一个例子讲清楚线程间同步、互斥量、条件变量、队列、内存池

前段时间有朋友想要了解一下多线程编程,正好有个项目上有这么个例子可以抽出来讲一讲。只要搞清楚这个例子,就一下子掌握了线程间同步、互斥量、条件变量、队列、内存池的概念和使用。 首先,线程间同步的概念。 比如,学过数字电路的人都知道,两个时钟域的信号如果没有经过同步直接接到一起的话,会引起亚稳态。原因是如果恰好输入信号在时钟边沿附近变化的话(不满足建立保持时间的情况下),信号可能处于一个中间电平,这样会导致触发器处于一个振荡状态,引起整块数字电路的不稳定。这就是数字电路中异步的概念,两个时钟都是各自free running,彼此没有关系。 再比如单片机程序中,各个不同的中断程序或者跟主程序间是异步的,因为主程序在执行的过程中随时可能被进来的中断打断,如果中断和主程序之间要通过一个共享的变量传递数据,你就要注意这个共享的变量的保护。假如主程序只读取了一半的数据而被中断打断,然后中断程序中又更新了整个变量,这样的回到主程序继续执行时读到的数据就有一半是上一次的,一半是更新过的。这样的结果显然不是我们想要的。这里只是举了一个很明显的例子。更多的情况可以搜索一下“原子操作”。 所以在多线程环境下,我们就要注意线程间共享变量的保护,这块敏感区域叫临界区(Critical area)。在单片机中,我们用中断开关来保护共享变量读写操作的完整性。在操作系统中,我们用的是互斥锁(mutex)来占有这个变量,防止它被多个线程同时访问。当一个线程访问当前已经被另一个线程占有的变量时,就会进入阻塞态,直到另一个线程完成解锁操作后,这个线程将得到继续执行。 互斥锁(mutex)是多线程编程时最重要的一个工具,用来解决多线程竞争同个资源的问题。其最底层的实现都是一个原子操作来界定lock or unlock。 接下来的例子创建了两个线程,一个是producer, 另一个是cusumer, 它们两个是异步的,中间通过一个队列来通讯。producer 向队列中发送数据,cusumer读取数据。模拟了一个场景:producer 以较快的速度向队列写数据,cusumer 处理数据较慢。这在图像帧处理时经常会碰到CPU处理和发送数据较慢,而外设采集速度较快的情况,这样多余的帧将被丢弃。队列节点使用自己写的一个内存池来分配,在malloc_node 从内存池(free_queue)里取出node; release_node 时把节点放回资源池。当对free_queue 进行操作的时候都要加锁,因为malloc_node 和release_node 可能被不同的线程调用,必须对free_queue 进行保护。这样的函数称之为是线程安全的。同理对enqueue,dequeue的操作也要对队列进行保护。 然后使用条件变量来通知consumer 队列有新数据到来。条件变量同样是被多个线程调用,也是需要带一个mutex 来进行保护的。当条件不满足时,线程会解锁mutex 进入block状态等待消息,这样才不会一直占有CPU。当条件满足或者超时时,才继续执行下面的程序。 例子中使用了pthread(POSIX thread) 的实现。其实各大操作系统都有自己的实现,FreeRTOS, Linux kernel等等,都可以拿代码过来看看学习。 请看这个多线程的例子,可以在online gdb 中运行调试: #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <pthread.h> #include <stdbool.h> #include <assert.h> #include <sys/time.h> #include <errno.h> /\*\*\*\*\*\*\*\*\*\*\*\* queue manage \*\*\*\*\*\*\*\*\*\*\*/ typedef struct Node { void \*data; struct Node \*next; }queue\_node\_t; #define BUFFER\_POOL\_SIZE (640 \* 480) #define BUFFER\_POOL\_NUM 5 struct pbuf{ uint32\_t len; uint8\_t payload\[BUFFER\_POOL\_SIZE\]; }; typedef struct QueueList { int sizeOfQueue; uint16\_t memSize; queue\_node\_t \*head; queue\_node\_t \*tail; }queue\_t; /\* to inform consumer\_thread \*/ static pthread\_cond\_t cap\_cond; static pthread\_mutex\_t cap\_mutex; /\* stream queue for communicate between two threads \*/ static queue\_t strm\_queue; static pthread\_mutex\_t strmq\_mutex; int strm\_queue\_init(){ queue\_t \*q = &strm\_queue; q->sizeOfQueue = 0; q->memSize = 0; q->head = q->tail = NULL; if (pthread\_cond\_init(&cap\_cond, NULL) !

ARM NEON Usage Note

简介 SIMD, 即Single Instruction Multiple Data(单指令多数据)的并行操作。CPU 在处理向量数据时有它的局限性。CPU的优势在于处理复杂多变的指令,而对于那种大数据量的重复性操作,ARM 为了增加处理效率,增加了这种并行处理模块, 即NEON(Advanced SIMD)。主要是在ARMv7 架构后的处理器使用。 NEON 的主要 components: NEON register file NEON integer execute pipeline NEON single-precision floating-point execute pipeline NEON load/store and permute pipeline NEON 指令和 floating-point 指令使用的是相同的 register file。不同于ARM core的register file。此 register file 可以以 32-bit, 64-bit, 128-bit 方式访问。 The contents of the NEON registers are vectors of elements of the same data type. A vector is divided into lanes and each lane contains a data value called an element.

H.264 codec Note

• Elements of a video Sequence o Frames o Slices o MBs (macroblocks) • Frame Types o I-, P-, B-frames o GOP (group of picture), specifies the order in which intra- and inter-frames are arranged. o NAL (Network Abstraction Layer) v SPS (Sequence parameter set) v PPS (Picture parameter set) v IDR (Instantaneous Decoder Refresh), every IDR frame is an I-frame, but not vice versa, • Coding Tools o Entropy Coding

Plans

Recently, I want to do some hardware acceleration applcations like using zynq to mining. This will help me more skillful in software and hardware combinational developments. This type of use case may be used in lot of scenes. Such hardware like DSP, VPU, GPU, neural stick and many fpga cores outside of CPU. I have to spend some time to read《FPGA based hardware accelerator for Dash mining》this thesis. Let’s go…

使用 qemu 调试 linux kernel

在 Ubuntu 中build kernel 参考如下: [Ref] https://wiki.ubuntu.com/KernelTeam/GitKernelBuild  可以直接在宿主机调试kernel, 但是当发生崩溃之后,工作环境又要重新配置。  所以考虑用 qemu,因为它有个option: -kernel, 可以直接引导kernel。比 VirtualBox 等虚拟机更快速更方便。 尝试使用 qemu 直接启动主机上的kernel  $ sudo qemu-system-x86\_64 -kernel /boot/vmlinuz-\`uname -r\` 这会提示缺少文件系统 可以使用 debootstrap 构建一个rootfs ``` IMG=qemu-image.img DIR=mount-point.dir qemu-img create $IMG 1g mkfs.ext2 $IMG mkdir $DIR sudo mount -o loop $IMG $DIR sudo debootstrap –arch amd64 jessie $DIR sudo umount $DIR rmdir $DIR 这里最好用一下 chroot 和 passwd 更新一下文件系统里的密码,以免启动之后登不进去。