README.md

# 树莓派3B / 3B+

这是树莓派3B的Nerves基本配置。

![树莓派3B图](assets/images/raspberry-pi-3-model-b.png)

## 使用

最常见的使用Nerves的方法是使用`mix
nerves.new` 创建一个项目,导出`MIX_TARGET=rpi3`。
更多信息请参阅[入门指南](https://hexdocs.pm/nerves/getting-started.html#creating-a-new-nerves-app)。

如果设备需要对系统进行自定义修改,
请复制此存储库并按[创建自定义系统](https://hexdocs.pm/nerves/systems.html#customizing-your-own-nerves-system)中所描述的进行更新

如果你对Nerves不熟悉,请浏览
[nerves_init_gadget](https://github.com/nerves-project/nerves_init_gadget)
来创建第一个项目。它将帮助您开始一些基础工作, 如建立网络、初始化可写应用程序数据分区以及启用基于ssh的固件更新。
使用有线以太网接口“Eth0”和DHCP是最容易的。

## 支持的WiFi设备

基础镜像包括树莓PI 3的WiFi模块(`brcmfmac` 驱动程序)。

## 音频

树莓PI有很多音频输出选项。该系统支持HDMI和立体声音频插孔输出,The Linux ALSA 驱动程序用于音频
输出。

试一试,运行:

```elixir
:os.cmd('espeak -ven+f5 -k5 -w /tmp/out.wav Hello')
:os.cmd('aplay -q /tmp/out.wav')
```

一般的树莓PI的音频文件适用于Nerves。
例如,强制将音频输出到HDMI端口,运行:

```elixir
:os.cmd('amixer cset numid=3 2')
```

将最后一个`amixer`参数更改为`1` 输出到立体声。

## Linux的preempt_rt 补丁

如果您需要从Linux内核获得更好的实时性能,`preempt_rt`
修补程序集可能会有所帮助。注意,我们没有测试的补丁,所以这可能无法工作。
 若要启用它,请使用一个自定义系统作为基础,并向`nerves_defconfig`添加以下内容:

```text
BR2_LINUX_KERNEL_PATCH="http://cdn.kernel.org/pub/linux/kernel/projects/rt/4.14/patch-4.14.71-rt44.patch.xz"
```

请验证补丁版本,因为这些指令可能过期。

接下来,更新Linux配置以使用它。 浏览文件,运行`make linux-menuconfig`并启用`PREEMPT_RT_FULL`。
另外,对Linux配置进行以下更改:

```text
-CONFIG_PREEMPT=y
+CONFIG_PREEMPT_RT_FULL=y
 ```

构建系统,你现在应该有一个preempt_rt内核。

## 配置设备

该系统支持将配置信息存储在文件系统之外的key-value存储区中。配置是可选的步骤,如果缺少,则使用合理的默认值。

配置信息可以使用Nerves.Runtime KV存储的
[`Nerves.Runtime.KV.get/1`](https://hexdocs.pm/nerves_runtime/Nerves.Runtime.KV.html#get/1)函数。

本系统使用的关键字为:

关键字                    | 例如     | 描述
:--------------------- | :---------------- | :----------
`nerves_serial_number` | `"12345678"`      | 默认情况下,此字符串用于创建单一主机名和Erlang节点的名称。如果未设置,它默认为树莓PI的设备ID的一部分。

正常的程序是在制造前或部署前设置这些键,然后将它们单独保存。

例如,要在运行的设备上提供序列号,请运行以下内容并重新启动:

```elixir
iex> cmd("fw_setenv nerves_serial_number 12345678")
```

该系统支持离线设置序列号。为此需在烧录固件时设置
`NERVES_SERIAL_NUMBER`环境变量。如果使用`fwup`编写MicroSD卡,则命令行为:

```sh
sudo NERVES_SERIAL_NUMBER=12345678 fwup path_to_firmware.fw
```

序列号被存储在MICROSD卡上,所以如果MICROSD卡被替换,序列号将需要被重新编写。这些数字存储在U-boot环境块中。
 这是一个与应用程序分区分离的特殊区域,因此重新格式化应用程序分区不会丢失序列号或存储在此块中的任何其他数据。

可以通过设置环境变量`NERVES_PROVISIONING=/path/to/provisioning.conf`来覆盖默认的provisioning.conf文件位置用来提供其他键值对。
默认的provisioning.conf用来设置`nerves_serial_number`,如果重写此文件的位置,则需要您将自己负责设置。

## Linux内核与RPI固件/用户空间

在这里使用的`nerves_system_br` 版本和Linux内核版本之间有微妙的耦合。
 `nerves_system_br` 提供了安装的 `rpi-userland`和`rpi-firmware`版本。
 我更喜欢将它们与Linux内核相匹配,以避免任何问题发生。
不幸的是,这些都没有被树莓PI基金会标记,所以要么尝试匹配Raspbian中的内容,要么采用具有相似提交时间的版本库。

## Linux内核配置

为Nerves编译的Linux内核默认是树莓Pi Linux内核的精简版本。
这样做是为了去除不必要的功能,选用一些Nerves特性,并节省空间。
若要使用这里的内核配置,请执行以下操作(这有点乏味):

1. 从`arch/arm/configs/bcmrpi_defconfig`开始。这是在官方Raspberry Pi镜像中使用的内核配置。
1. 关闭除`ext4`, `squashfs`, `tmpfs`, `proc`,`sysfs`, 和 `vfat`之外的所有文件系统。 只需要ZLIB支持。
1. `vfat` 默认为 `utf8`. 启用`ascii`, `utf-8`, `ISO 8859-1`, 代码页 437, 和代码页 850的本机语言支持。
1. 禁用 Broadcom FullMAC WLAN 以外的所有网络驱动程序和无线局域网驱动程序。
1. 禁用 PPP 和 SLIP。
1. 禁用驱动程序菜单中的WiFi驱动程序。
1. 在多媒体支持菜单中禁用 TV, AM/FM, 媒体USB适配器, DVB前端和远程控制器支持。
1. 转到`Device Drivers->Sound card support`。禁用ALSA中的`USB sound devices`, 禁用 `Open Sound System`.
1. 转到`Device Drivers->Graphics support`. 禁用 `DisplayLink`
1. 在 `Kernel Features`中, 选择 `Preemptible Kernel (Low-Latency Desktop)`,
   禁用压缩页的内存分配器。
1. 在 `Userspace binary formats`中, 禁用对MISC二进制文件的支持。
1. 在 `Networking support`中, 禁用业余无线电支持、CAN总线子系统、IrDA子系统、蓝牙、WiMAX、Plan 9和NFC。
(这可能太苛刻了,如果使用这些中的任何一个,请提出问题,这是创建自定义系统的唯一原因)。
1. 在 `Networking options`, 禁用IPSec,SCTP协议802.1D以太网,异步传输模式,桥接,L2TP, VLAN, AppleTalk, 6LoWPAN 802.15.4,DNS,旋转变压器, B.A.T.M.A.N, 虚拟交换机, MPLS, 以及网络测试中的包生成器。
1. 在 `Networking support->Wireless`中, 启用 "use statically compiled regulatory
   rules database"。内置`cfg80211` 和 `mac80211`。关闭`mac80211`网状网络和LED触发器。
   关闭 `cfg80211` 无线扩展兼容性。
1. 在 `Kernel hacking`中, 禁用 KGDB, 和 Magic SysRq key.
1. 在设备驱动程序中,禁用MTD支持。在块设备中,禁用除了回环和RAM块设备以外的所有设备。禁用RAID和LVM。
1. 在 `Enable the block layer`中, 取消选择一切,但PC BIOS分区类型(即,没有MAC分区支持等)。
1. 在 `Enable loadable module support`中, 选择 "Trim unused exported kernel symbols"。
注意:如果你在一个树外内核模块构建中遇到问题,试着删除这个!!
1. 在 `General Setup`中, 关闭 `initramfs/initfd` 支持, 关闭Kernel .config
   支持, 关闭OProfile.
1. 在 `Device Drivers -> I2C -> Hardware Bus Support`中,  将模块编译到内核中,并禁用除了`BCM2708 BSC`支持之外的所有功能。
1. 在 `Device Drivers -> SPI`中, 编译BCM2835 SPI 控制器和用户模式SPI 设备驱动支持。
1. 在 `Device Drivers -> Staging`中, 禁用`Support for small TFT LCD modules`
1. 在 `Device Drivers -> Dallas's 1-wire support`中,  除了GPIO 1-主线和温度计外,禁用其他。(注:为什么温度计编译? 这似乎是个历史问题。)
1. 禁用 `Hardware Monitoring support`, `Sonics Silicon Backplane support`
1. 在 `Device Drivers -> Character devices -> Serial drivers`中,  禁用8250和SC16IS7xx支持。禁用原始驱动程序。
1. 在 `Networking support->Network options`中,  禁用 `IP: kernel level autoconfiguration`
1. 在 `Networking support->Network options->TCP: advanced congestion control`中,
   禁用除`CUBIC TCP`以外的所有内容。
1. 禁用 `Real Time Clock`.
1. 禁用`Cryptographic API` 和 `Library routines`中的所有内容。有时你需要多次尝试。
1. 禁用EEPROM 93CX6支持、PPS支持、所有GPIO扩展器、语音核心、媒体分级驱动程序、意法半导体STMPE、全部"Wolfson"。
1. 禁用大多数ALSA的SoC音频支持和编解码器。注意:我们可能应该支持一些,但是我不知道哪些是最有用的,而且列表中还有很多设备驱动程序。
1. 禁用IIO和UIO。
1. 禁用NXP PCA9685 PWM驱动器