Upon reboot, you will find that one or both of these pins are set to high due to them being booted into ALT0 (read: UART) mode. This obviously causes problems if you are using these pins for GPIO in an application (unless you can ensure that your Pi is *never* rebooted). I have tried in vain to find a solution for this, but it seems to be a firmware issue (or at least baked deeply into the kernel). The following post simply documents what I tried, but it provides insight on two things: how to deactivate the default serial console running on /dev/ttyAMA0, and how to compile a custom kernel for your Raspberry Pi.
tl;dr: Tried to completely disable UART (pins 8 and 10) on a Raspberry Pi by forcing it not to boot into ALT0 mode. You can't, it seems - or at least I have not found a method. Please leave comment if you know of a way!
My attempt: disable serial console, then remove UART drivers from kernel
Note: I started down this path because pins 8 and 10 on the Pi are not driven high when the Pi is turned on without an SD card (i.e. without an operating system). This led me to suspect that the OS is setting the pins into ALT0 mode in software. As far as I can tell, I was wrong. Now I suspect it's the firmware, but that's sadly not solved as easily.
The serial console device /dev/ttyAMA0 is created automatically by the default Raspbian kernel (since it uses it for diagnostic- and boot messages, and as a login console) and because of this, the UART driver is compiled directly into to the kernel and not as an unloadable module. The following steps changes that, first by deactivating most serial messages and the serial login prompt. Next, the kernel is recompiled to build the UART driver as a separate unloadable module. Finally, the UART driver is disabled.
- Disable boot- and debug message logging to the serial console (this is configured to be active by default on Raspbian):
Edit /boot/cmdline.txt:sudo vim /boot/cmdline.txt
Remove the options referring to the serial console ("/dev/ttyAMA0"); in other words, change it from this:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
to this:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
- Next you must disable the serial console login prompt. Edit /etc/inittab:
sudo vim /etc/inittab
At the end of the file you will find the following line:T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Disable it by commenting it out (put a # character at the start of the line), or delete it. - Longest step: Kernel recompilation
Before you start, make sure your system is up to date:sudo apt-get update sudo apt-get dist-upgrade
Next, install the compiler and some packages needed for recompiling the kernel:sudo apt-get install gcc make git libncurses5-dev
Make and change into a directory in which you can build the kernel:sudo mkdir /opt/build sudo chmod 777 /opt/build cd /opt/build
Download a copy of the kernel source from the github repository:git clone --depth 1 git://github.com/raspberrypi/linux.git cd linux
Now you are ready to configure and rebuild the kernel. First, make sure your build directory is clean:make mrproper
Next, save the configuration of your currently-running kernel (this allows your new kernel to be configured based on your current kernel settings, which saves a lot of time):zcat /proc/config.gz > .config
To ensure that your current kernel configuration is up-to-date with the kernel you downloaded, do:make oldconfig
Now we are going to modify the kernel to modularize the UART driver and remove bootup dependencies on it:make menuconfig
You will be presented with the Linux kernel configuration menu. Since the configuration is based on your currently-running kernel's configuration, we only need to change two things:
- Disable all /dev/ttyAMA0 kernel boot messages: Highlight "Boot options" and press [ENTER]. Now highlight the "Default kernel command string"; it will look like the following:
(dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait)
Press [ENTER] to select it. Edit the string and remove the "console" and "kgdboc" options; i.e. change it to:
dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
Once edited, press [ESC] twice to go back to the previous level. Continue pressing [ESC] until you get back to the main menu.
- Modularize UART driver (so that it can be disabled): From the main kernel configuration menu, go to Device Drivers -> Character devices -> Serial drivers, then highlight "ARM AMBA PL011 serial port support" and press M to modularize it.
Now press [ESC] until you get back to the main menu. Press [ESC] twice again, and save the configuration when prompted.
make && make modules
- Disable all /dev/ttyAMA0 kernel boot messages: Highlight "Boot options" and press [ENTER]. Now highlight the "Default kernel command string"; it will look like the following:
- Install the custom kernel
Your newly-built kernel image will be /opt/build/linux/arch/arm/boot/Image. Copy the new kernel image to the Raspberry Pi's boot partition, using a different name in case you need to roll back later:sudo cp -v arch/arm/boot/Image /boot/kernel_mod_uart.img
Now edit the file /boot/config.txt:sudo vim /boot/config.txt
In this file, change the "kernel=" line to the following (or add it if it does not exist):kernel=kernel_mod_uart.img
Finally, install the kernel modules that you compiled earlier, by issuing (in your build directory):sudo make modules_install
You have now replaced the default kernel with your "UART-as-a-module" version. Reboot the Raspberry Pi to load the new kernel and ensure everything is OK. - Final step: Disable UART driver module
The new kernel still loads and sets up the UART device, but now you can disable it. Edit the file /etc/modprobe.d/raspi-blacklist.conf:sudo vim /etc/modprobe.d/raspi-blacklist.conf
Add the following line to the file, and save it:blacklist amba_pl011
You may now reboot the Pi for the changes to take affect, or simply remove the already-loaded driver directly by entering:sudo rmmod amba_pl011
Conclusion
Sadly, pins 8 and 10 of the Raspberry Pi are still set to ALT0 mode upon bootup after applying the changes documented above. I have not looked into the kernel source for other clues (for my needs it is far simpler to use two different pins). If you know of way to force them to be set to GPIO mode (and driven LOW), please let me know.
No comments:
Post a Comment