沁恒CH32V103C8T6(二): Linux RISC-V编译和烧录环境配置
目录
硬件准备
- CH32V103 开发板/核心版
- WCH-Link
软件准备
软件主要是用于编译的 RISC-V GCC , 和用于烧录的 OpenOCD.
- RISC-V GCC 可以选择公版或者WCH版
- OpenOCD 暂时只能用WCH定制版本, 用公版的无法识别 wlink
公版 RISC-V GCC
前往 https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases 下载
MounRiver 提供的工具链, 包含 RISC-V GCC 和 OpenOCD
前往 http://mounriver.com/download 下载 MRS_Toolchain_Linux_x64, 当前是 MRS_Toolchain_Linux_x64_V1.50.tar.xz, RISC-V GCC 版本为 8.2.0.
解压工具链压缩包, 目录结构为
── beforeinstall
│ ├── 50-wch.rules
│ ├── 60-openocd.rules
│ ├── libhidapi-hidraw.so -> libhidapi-hidraw.so.0.0.0
│ ├── libhidapi-hidraw.so.0 -> libhidapi-hidraw.so.0.0.0
│ ├── libhidapi-hidraw.so.0.0.0
│ ├── libhidapi-libusb.so -> libhidapi-libusb.so.0.0.0
│ ├── libhidapi-libusb.so.0 -> libhidapi-libusb.so.0.0.0
│ ├── libhidapi-libusb.so.0.0.0
│ ├── libjaylink.so -> libjaylink.so.0.1.0
│ ├── libjaylink.so.0 -> libjaylink.so.0.1.0
│ ├── libjaylink.so.0.1.0
│ ├── libmcuupdate.so
│ ├── libncurses.so.5 -> libncurses.so.5.9
│ ├── libncurses.so.5.9
│ ├── libtinfo.so.5 -> libtinfo.so.5.9
│ ├── libtinfo.so.5.9
│ ├── libusb-1.0.so -> libusb-1.0.so.0.3.0
│ ├── libusb-1.0.so.0 -> libusb-1.0.so.0.3.0
│ ├── libusb-1.0.so.0.3.0
│ └── start.sh
├── OpenOCD
│ ├── bin
│ │ ├── openocd
│ │ ├── wch-arm.cfg
│ │ └── wch-riscv.cfg
│ ├── README.md
│ └── share
├── README
└── RISC-V Embedded GCC
├── bin
├── distro-info
├── include
│ └── gdb
│ └── jit-reader.h
├── lib
│ ├── bfd-plugins
│ └── gcc
├── lib64
│ ├── libcc1.so -> libcc1.so.0.0.0
│ ├── libcc1.so.0 -> libcc1.so.0.0.0
│ ├── libcc1.so.0.0.0
│ ├── libgcc_s.so.1
│ ├── libstdc++.so.6 -> libstdc++.so.6.0.24
│ └── libstdc++.so.6.0.24
├── libexec
│ └── gcc
├── README.md
├── riscv-none-embed
└── share
其中
- beforeinstall 目录下是需要配置到Ubuntu中的动态链接库文件, 和设备规则文件
- start.sh 这个文件里面有设置环境的命令
- OpenOCD 这个目录下有一定制的 openocd 可执行文件, 以及对应的 wch-arm 和 wch-riscv 的配置文件
- RISC-V Embedded GCC RISC-V 编译器
安装
RISC-V GCC 安装
这部分比较简单, 在 /opt 目录下建一个 gcc-riscv 目录, 将工具解压后复制过去, 用公版或WCH工具链中带的版本都行. 设置好相应的权限, 路径在后面配置 Makefile 的时候需要使用, 用 --version
验证一下是否正常
/opt/gcc-riscv$ /opt/gcc-riscv/riscv-none-embed-gcc-10.2.0-1.2/bin/riscv-none-embed-gcc --version
riscv-none-embed-gcc (xPack GNU RISC-V Embedded GCC x86_64) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
OpenOCD 安装
也是解压后复制到 /opt 目录下, 验证一下
/opt/gcc-riscv$ /opt/openocd/wch-openocd/bin/openocd --version
Open On-Chip Debugger 0.11.0+dev-02215-gcc0ecfb6d-dirty (2022-06-23-10:21)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
环境配置
在openocd可以正常烧录前, 需要进行一些环境配置, 参考 WCH 工具包下的 beforeinstall 目录
1. 配置动态链接库
因为环境中还安装了其他的工具, 为避免冲突, 对 start.sh 中的步骤手工安装. 在 /usr/lib 下创建一个单独的目录, 用于放置这些动态链接库文件
cd /usr/lib
sudo mkdir wch-moun-river
sudo cp ./beforeinstall/lib* wch-moun-river/
为这个新的链接库文件目录增加ldconfig配置, 在 /etc/ld.so.conf.d/ 下创建文件 wch-moun-river.conf , 内容如下
more /etc/ld.so.conf.d/wch-moun-river.conf
# lib for wch moun river studio
/usr/lib/wch-moun-river
然后更新生效
sudo ldconfig
如果出现这样的提示, 说明环境中存在多个同样名称的动态链接库, 如果不想看到这些警告可以将这些文件删除, 也可以忽略
/sbin/ldconfig.real: /usr/lib/wch-moun-river/libtinfo.so.5 is not a symbolic link
2. 配置设备权限
先检查一下 /etc/udev/ 下是否已经存在相关的配置, 如果有, 需要和这两个规则整合一下, 如果没有, 直接复制然后更新就可以了
sudo cp ./50-wch.rules /etc/udev/rules.d
sudo cp ./60-openocd.rules /etc/udev/rules.d
# Reload rules
sudo udevadm control --reload-rules
3. 检查是否生效
将 WCH-Link 和开发板连接到电脑, 此时dmesg应该能正常检测到 WCH-Link 设备, 检查一下 WCH-Link 是否运行在 WCH-Link 模式, 如果运行在 DAP-Link模式下, 需要切换一下.
[ 2449.285125] usb 2-3: USB disconnect, device number 2
[ 2452.341042] usb 2-3: new full-speed USB device number 5 using xhci_hcd
[ 2452.494530] usb 2-3: New USB device found, idVendor=1a86, idProduct=8010, bcdDevice= 2.05
[ 2452.494543] usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2452.494549] usb 2-3: Product: WCH-Link
[ 2452.494554] usb 2-3: Manufacturer: wch.cn
[ 2452.494558] usb 2-3: SerialNumber: 0001A0000000
[ 2452.498525] cdc_acm 2-3:1.1: ttyACM0: USB ACM device
到工具链解压目录下, 用 OpenOCD 检查是否能正常连接
./openocd -f wch-riscv.cfg -c init -c halt
# 如果有以下的显示说明配置正确
Open On-Chip Debugger 0.11.0+dev-02215-gcc0ecfb6d-dirty (2022-06-23-10:21)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Ready for Remote Connections
Info : WCH-Link-CH549 mod:RV version 2.5
Info : wlink_init ok
Info : This adapter doesn't support configurable speed
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Warn : Bypassing JTAG setup events due to errors
Info : [riscv.cpu.0] datacount=2 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x0
[riscv.cpu.0] Target successfully examined.
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
如果显示下面的错误, 说明动态链接库配置有误
./openocd: symbol lookup error: ./openocd: undefined symbol: jaylink_device_get_usb_bus_ports
如果显示下面的错误, 说明使用的不是 wch 提供的定制 openocd
wch-riscv.cfg:2: Error: invalid command name "adapter"
in procedure 'script'
at file "embedded:startup.tcl", line 60
at file "wch-riscv.cfg", line 2
运行示例项目
导出项目
从 GitHub 导出项目到本地
git clone https://github.com/IOsetting/ch32v103-template.git
修改项目配置
打开 Makefile 将工具路径配置为自己的路径
TOOL_CHAIN_PATH ?= /opt/gcc-riscv/riscv-none-embed-gcc-10.2.0-1.2/bin
OPENOCD_PATH ?= /opt/openocd/wch-openocd/bin
项目名称可以修改
PROJECT_NAME = test001
编译项目
# 清理
make clean
# 编译
make
烧录
make flash
附录
编译命令和参数说明
编译命令的基本格式如下
riscv-none-embed-gcc
-march=rv32imac
-mabi=ilp32
-msmall-data-limit=8
-mno-save-restore
-Os
-fmessage-length=0
-fsigned-char
-ffunction-sections
-fdata-sections
-Wunused
-Wuninitialized
-g
-I"/home/milton/WorkRiscV/ch32v_ws001/ch32v103_test001/Debug"
-I"/home/milton/WorkRiscV/ch32v_ws001/ch32v103_test001/Core"
-I"/home/milton/WorkRiscV/ch32v_ws001/ch32v103_test001/User"
-I"/home/milton/WorkRiscV/ch32v_ws001/ch32v103_test001/Peripheral/inc"
-std=gnu99
-MMD
-MP
-MF"Peripheral/src/ch32v10x_crc.d"
-MT"Peripheral/src/ch32v10x_crc.o"
-c
-o "Peripheral/src/ch32v10x_crc.o"
"../Peripheral/src/ch32v10x_crc.c"
各参数的说明, 引自 RISC-V-Options, GCC C Dialect Options GCC Preprocessor Options
-march=ISA-string 设置指令集架构
Generate code for given RISC-V ISA (e.g. ‘rv64im’). ISA strings must be lower-case. Examples include ‘rv64i’, ‘rv32g’, ‘rv32e’, and ‘rv32imaf’.
When -march= is not specified, use the setting from -mcpu.
If both -march and -mcpu= are not specified, the default for this argument is system dependent, users who want a specific architecture extensions should specify one explicitly.
-mabi=ABI-string 设置应用程序二进制接口
Specify integer and floating-point calling convention. ABI-string contains two parts: the size of integer types and the registers used for floating-point types. For example ‘-march=rv64ifd -mabi=lp64d’ means that ‘long’ and pointers are 64-bit (implicitly defining ‘int’ to be 32-bit), and that floating-point values up to 64 bits wide are passed in F registers. Contrast this with ‘-march=rv64ifd -mabi=lp64f’, which still allows the compiler to generate code that uses the F and D extensions but only allows floating-point values up to 32 bits long to be passed in registers; or ‘-march=rv64ifd -mabi=lp64’, in which no floating-point arguments will be passed in registers.
The default for this argument is system dependent, users who want a specific calling convention should specify one explicitly. The valid calling conventions are: ‘ilp32’, ‘ilp32f’, ‘ilp32d’, ‘lp64’, ‘lp64f’, and ‘lp64d’. Some calling conventions are impossible to implement on some ISAs: for example, ‘-march=rv32if -mabi=ilp32d’ is invalid because the ABI requires 64-bit values be passed in F registers, but F registers are only 32 bits wide. There is also the ‘ilp32e’ ABI that can only be used with the ‘rv32e’ architecture. This ABI is not well specified at present, and is subject to change.
-msmall-data-limit=n 将小于n字节的全局和静态数据放到一个特定区域
Put global and static data smaller than n bytes into a special section (on some targets).
-mno-save-restore
Do or don’t use smaller but slower prologue and epilogue code that uses library function calls. The default is to use fast inline prologues and epilogues.
-Os 尺寸优化
Optimize for size. -Os enables all -O2 optimizations except those that often increase code size:
-falign-functions -falign-jumps
-falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
-fmessage-length=n
Try to format error messages so that they fit on lines of about n characters. If n is zero, then no line-wrapping is done; each error message appears on a single line. This is the default for all front ends.
Note - this option also affects the display of the ‘#error’ and ‘#warning’ pre-processor directives, and the ‘deprecated’ function/type/variable attribute. It does not however affect the ‘pragma GCC warning’ and ‘pragma GCC error’ pragmas.
-fsigned-char
Let the type char be signed, like signed char.
Note that this is equivalent to -fno-unsigned-char, which is the negative form of -funsigned-char. Likewise, the option -fno-signed-char is equivalent to -funsigned-char.
-ffunction-sections, -fdata-sections
Place each function or data item into its own section in the output file if the target supports arbitrary sections. The name of the function or the name of the data item determines the section’s name in the output file.
Use these options on systems where the linker can perform optimizations to improve locality of reference in the instruction space. Most systems using the ELF object format have linkers with such optimizations. On AIX, the linker rearranges sections (CSECTs) based on the call graph. The performance impact varies.
Together with a linker garbage collection (linker --gc-sections option) these options may lead to smaller statically-linked executables (after stripping).
-Wunused
Warns, all the -Wunused options combined.
-Wuninitialized
Warn if an object with automatic or allocated storage duration is used without having been initialized. In C++, also warn if a non-static reference or non-static const member appears in a class without constructors.
-g
generates debug information to be used by GDB debugger.
- -g0 no debug information
- -g1 minimal debug information
- -g default debug information
- -g3 maximal debug information
-MD
-MD is equivalent to -M -MF file, except that -E is not implied. The driver determines file based on whether an -o option is given. If it is, the driver uses its argument but with a suffix of .d, otherwise it takes the name of the input file, removes any directory components and suffix, and applies a .d suffix.
-MMD
Like -MD except mention only user header files, not system header files.
-MP
This option instructs CPP to add a phony target for each dependency other than the main file, causing each to depend on nothing. These dummy rules work around errors make gives if you remove header files without updating the Makefile to match.
This is typical output:
test.o: test.c test.h
test.h:
-MF file
When used with -M or -MM, specifies a file to write the dependencies to. If no -MF switch is given the preprocessor sends the rules to the same place it would send preprocessed output.
When used with the driver options -MD or -MMD, -MF overrides the default dependency output file.
If file is -, then the dependencies are written to stdout.
-MT target
Change the target of the rule emitted by dependency generation. By default CPP takes the name of the main input file, deletes any directory components and any file suffix such as ‘.c’, and appends the platform’s usual object suffix. The result is the target.
An -MT option sets the target to be exactly the string you specify. If you want multiple targets, you can specify them as a single argument to -MT, or use multiple -MT options.
For example, -MT '$(objpfx)foo.o' might give
$(objpfx)foo.o: foo.c
烧录命令
# 擦写
./openocd -f wch-riscv.cfg -c init -c halt -c "flash erase_sector wch_riscv 0 last " -c exit
# 写入
./openocd -f wch-riscv.cfg -c init -c halt -c "program ./obj/ch32v103_test001.elf" -c exit
# 校验
./openocd -f wch-riscv.cfg -c init -c halt -c "verify_image ./obj/ch32v103_test001.elf" -c exit
# 重置,运行
./openocd -f wch-riscv.cfg -c init -c halt -c wlink_reset_resume -c exit
烧录命令执行记录
milton@/OpenOCD/bin$ ./openocd -f wch-riscv.cfg -c init -c halt -c "flash erase_sector wch_riscv 0 last " -c exit
Open On-Chip Debugger 0.11.0+dev-02215-gcc0ecfb6d-dirty (2022-06-23-10:21)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Ready for Remote Connections
Info : WCH-Link-CH549 mod:RV version 2.5
Info : wlink_init ok
Info : This adapter doesn't support configurable speed
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Warn : Bypassing JTAG setup events due to errors
Info : [riscv.cpu.0] datacount=2 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x0
[riscv.cpu.0] Target successfully examined.
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : device id = 0x3c83abcd
Info : flash size = 64kbytes
erased sectors 0 through 63 on flash bank 0 in 0.019672s
milton@/OpenOCD/bin$ ./openocd -f wch-riscv.cfg -c init -c halt -c "program ch32v103_test001/obj/ch32v103_test001.elf" -c exit
Open On-Chip Debugger 0.11.0+dev-02215-gcc0ecfb6d-dirty (2022-06-23-10:21)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Ready for Remote Connections
Info : WCH-Link-CH549 mod:RV version 2.5
Info : wlink_init ok
Info : This adapter doesn't support configurable speed
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Warn : Bypassing JTAG setup events due to errors
Info : [riscv.cpu.0] datacount=2 progbufsize=8
Info : Vector support with vlenb=0
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0xffffffff
[riscv.cpu.0] Target successfully examined.
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Warn : Bypassing JTAG setup events due to errors
** Programming Started **
Info : device id = 0x3c83abcd
Info : flash size = 64kbytes
** Programming Finished **
milton@/OpenOCD/bin$ ./openocd -f wch-riscv.cfg -c init -c halt -c "verify_image ch32v103_test001/obj/ch32v103_test001.elf" -c exit
Open On-Chip Debugger 0.11.0+dev-02215-gcc0ecfb6d-dirty (2022-06-23-10:21)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Ready for Remote Connections
Info : WCH-Link-CH549 mod:RV version 2.5
Info : wlink_init ok
Info : This adapter doesn't support configurable speed
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Warn : Bypassing JTAG setup events due to errors
Info : [riscv.cpu.0] datacount=2 progbufsize=8
Info : Vector support with vlenb=0
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0xffffffff
[riscv.cpu.0] Target successfully examined.
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
Info : Verify Success
milton@/OpenOCD/bin$ ./openocd -f wch-riscv.cfg -c init -c halt -c wlink_reset_resume -c exit
Open On-Chip Debugger 0.11.0+dev-02215-gcc0ecfb6d-dirty (2022-06-23-10:21)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
Ready for Remote Connections
Info : WCH-Link-CH549 mod:RV version 2.5
Info : wlink_init ok
Info : This adapter doesn't support configurable speed
Info : JTAG tap: riscv.cpu tap/device found: 0x00000001 (mfg: 0x000 (<invalid>), part: 0x0000, ver: 0x0)
Warn : Bypassing JTAG setup events due to errors
Info : [riscv.cpu.0] datacount=2 progbufsize=8
Info : Examined RISC-V core; found 1 harts
Info : hart 0: XLEN=32, misa=0x0
[riscv.cpu.0] Target successfully examined.
Info : starting gdb server for riscv.cpu.0 on 3333
Info : Listening on port 3333 for gdb connections
沁恒CH32V103C8T6(二): Linux RISC-V编译和烧录环境配置的更多相关文章
- 沁恒CH32V003(二): Ubuntu20.04 MRS和Makefile开发环境配置
目录 沁恒CH32V003(一): CH32V003F4P6开发板上手报告和Win10环境配置 沁恒CH32V003(二): Ubuntu20.04 MRS和Makefile开发环境配置 硬件准备 沁 ...
- 沁恒CH32F103C8T6(二): Linux PlatformIO环境配置, 示例运行和烧录
目录 沁恒CH32F103C8T6(一): Keil5环境配置,示例运行和烧录 沁恒CH32F103C8T6(二): Linux PlatformIO环境配置, 示例运行和烧录 StdPeriphLi ...
- 【泡咖啡1】linux下caffe编译以及python环境配置手记
caffe是一个深度学习的库,相信搞深度学习的话,不是用这个库就是用theano吧.要想使用caffe首先第一步就是要配置好caffe的环境.在这里,我主要说的是在debian的linux环境下如何配 ...
- Linux系统下安装jdk及环境配置(两种方法)
https://blog.csdn.net/qq_42815754/article/details/82968464 这里介绍两种linux环境下jdk的安装以及环境配置方法在windows系统安装j ...
- 沁恒CH32V103C8T6开发环境笔记
CH32V103C8T6 CH32V103C8T6是沁恒的RISC-V内核MCU, 基于RISC-V3A处理器, 内核采用2级流水线处理,设置了静态分支预测.指令预取机制,支持DMA. 主要参数如下 ...
- thrift 服务端linux C ++ 与客户端 windows python 环境配置(thrift 自带tutorial为例)
关于Thrift文档化的确是做的不好.摸索了很久才终于把跨linux与windows跨C++与python语言的配置成功完成.以下是步骤: 1) Linux下环境配置 ...
- Linux系统下安装JDK及环境配置
第一种属于傻瓜式安装,一键安装即可(yum安装): 第二种手动安装,需要自己去Oracle官网下载需要的jdk版本(需官网注册登录才可以下载),然后解压并配置环境. 一.yum一键安装1.首先执行以下 ...
- 三叔学FPGA系列之二:Cyclone V中的POR、配置、初始化,以及复位
对于FPGA内部的复位,之前一直比较迷,这两天仔细研究官方数据手册,解开了心中的诸多疑惑,感觉自己又进步了呢..... 原创不易,转载请转原文,注明出处,谢谢. 一.关于POR(Power-On ...
- 二维码解码器Zbar+VS2012开发环境配置
Zbar条码解码器是一个开源的二维码(包括条形码)解码器,可以识别来至于视频流,图像文件.手持扫码器和视频设备(如摄像头)等二维码识别,支持EAN-13/UPC-A, UPC-E, EAN-8, Co ...
随机推荐
- Go Context 原理详解
实现一个小目标 很开心的一件事,学习了一个月的后端拿到一个13k的offer,今年年底目标拿到一个30k的go方向offer. 好了回归正文,这篇文章是回答交流时一个老哥的问题,跟go的context ...
- c++:-2
上节介绍C++的函数介绍:c++:-1,本节学习类与对象 类与对象 定义 类定义 class 类名称 { public: 公有成员(外部接口) private: 私有成员 protected: 保护型 ...
- 你不知道的 Linux 使用技巧
开源Linux 一个执着于技术的公众号 1.快速跳转命令 - z 要是每次都要进入一个目录很深的文件夹下,像下面这样: # cd /root/py/auto/fabric 每次都要输入好多个目录名是不 ...
- js动态生成vue组件
代码奉上 install (Vue, options) { Vue.prototype.$message = function (message){ let Constructor = Vue.ext ...
- 【hexo博客搭建】将搭建好的hexo博客部署到阿里云服务器上面(下)
一.部署到阿里云服务器 既然博客也已经成功在本地部署,然后主题也成功安装,接下来就可以部署到服务器上面了,如果你也想要魔改matery主题,可以去各种博客上面找一找大佬的教程,或者联系我,也可以让你少 ...
- 腾讯tbs 内存泄露
一.背景 TBS(腾讯浏览服务)是腾讯提供的移动端webview体验的整套解决方案(https://x5.tencent.com/docs/index.html),可以用于移动端加载doc.xls.p ...
- OpenStack 安装 Keystone
OpenStack 安装 Keystone 本篇主要记录一下 如何安装 openstack的 第一个组件 keystone 认证授权组件 openstack 版本 我选的是queens 版本 1.Op ...
- Cubieboard安装系统
2013年买的一个小玩意. 一.硬件 1.1 相关资料 http://www.cubieforums.com http://cubie.cc 1.2 cubieboard1 1.3 无线网卡 水星 M ...
- unity---给物体施加普通力和位置力
普通力 让物体沿着某一方向获得一个力,vector3方向 addForceObj.GetComponent<Rigidbody>().AddForce(1000,0,1000); 位置力 ...
- 面试突击51:为什么单例一定要加 volatile?
单例模式的实现方法有很多种,如饿汉模式.懒汉模式.静态内部类和枚举等,当面试官问到"为什么单例模式一定要加 volatile?"时,那么他指的是为什么懒汉模式中的私有变量要加 vo ...