[[PageOutline]] = Ubuntu = Gateworks supports the popular Ubuntu OS on Newport and Ventana products using an Ubuntu built root filesystem with a Gateworks kernel. In some cases you may be able to use an Ubuntu built kernel. Gateworks always tries to use the LTS releases (Long Term Support). * Jammy Jellyfish 22.04 * Focal Fossa 20.04 In addition to the information on this page, you likely want to look at product family specific details on the following pages for your product: * [wiki:venice/ubuntu Venice Ubuntu Page] * [wiki:newport/ubuntu Newport Ubuntu Page] * [wiki:ventana/ubuntu Ventana Ubuntu Page] [[Image(ubuntufocalwithversion.png,300px)]] == Ubuntu root filesystem Creating a root filesystem comprised of Canonical built packages can be done in a couple of ways: * download a pre-built rootfs tarball * create one using deboostrap * create one using qemu/chroot This refers to the rootfs only. To easily build an entire system image, including the boot firmware and Ubuntu, look at the BSP for the various product families: * [wiki:malibu/bsp Malibu BSP] * [wiki:venice/bsp Venice BSP] * [wiki:newport/bsp Newport BSP] === Downloading pre-built rootfs tarball Gateworks has pre-built Ubuntu based rootfs tarballs at http://dev.gateworks.com/ubuntu/ that are created with the [https://github.com/gateworks/ubuntu-rootfs ubuntu-rootfs script]. [=#qemu-chroot] === Creating Ubuntu rootfs using qemu and chroot You can use qemu to create an Ubuntu based rootfs with very little in the way of dependencies. To do this you must boot a virtual machine for your architecture therefore you will need a kernel and a minimal root filesystem which can be easily built using buildroot. Example: * aarch64 rootfs: 1. Start by defining some parameters {{{#!bash IMG=ubuntu.ext4 SIZE=500M UBUNTU=22.04 UBUNTU_REL=.3 }}} 1. Create a ramdisk based image (similar concept as rescue image but we add a file here via BR2_ROOTFS_OVERLAY) {{{#!bash sudo apt install build-essential git git clone http://github.com/buildroot/buildroot.git cd buildroot cat << EOF > configs/buildroot_defconfig BR2_aarch64=y BR2_cortex_a72=y BR2_TOOLCHAIN_BUILDROOT_GLIBC=y BR2_TOOLCHAIN_BUILDROOT_CXX=y BR2_TARGET_GENERIC_HOSTNAME="localhost" BR2_ROOTFS_OVERLAY="overlay/" BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y BR2_PACKAGE_E2FSPROGS=y # BR2_PACKAGE_E2FSPROGS_FSCK is not set BR2_PACKAGE_I2C_TOOLS=y BR2_PACKAGE_RNG_TOOLS=y BR2_PACKAGE_BASH=y BR2_PACKAGE_TAR=y BR2_PACKAGE_UTIL_LINUX_HWCLOCK=y BR2_TARGET_ROOTFS_CPIO=y BR2_TARGET_ROOTFS_CPIO_GZIP=y EOF # create init script mkdir -p overlay/etc/init.d cat < overlay/etc/init.d/S99boostrap-ubuntu.sh #!/bin/sh if [ "\$1" != "start" ]; then exit fi # setup mkfs.ext4 -F /dev/vda -b 4096 mount /dev/vda /mnt cd /mnt/ udhcpc -i eth0 # install base rootfs from release tarball wget -c -P /tmp/ http://cdimage.ubuntu.com/ubuntu-base/releases/${UBUNTU}/release/ubuntu-base-${UBUNTU}${UBUNTU_REL}-base-arm64.tar.gz tar zxf /tmp/ubuntu-base-${UBUNTU}${UBUNTU_REL}-base-arm64.tar.gz -C /mnt # setup chroot environment mount -o bind /proc /mnt/proc/ mount -o bind /sys/ /mnt/sys/ mount -o bind /dev/ /mnt/dev/ mount -o bind /dev/pts /mnt/dev/pts mount -t tmpfs tmpfs /mnt/var/lib/apt/ mount -t tmpfs tmpfs /mnt/var/cache/apt/ echo "nameserver 8.8.8.8" > /mnt/etc/resolv.conf echo "localhost" > /mnt/etc/hostname echo "127.0.0.1 localhost" > /mnt/etc/hosts export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C # install additional packages chroot /mnt apt update chroot /mnt apt upgrade -y chroot /mnt apt install --no-install-recommends -y \ apt-utils locales less wget procps \ psmisc less sudo kmod rng-tools \      ifupdown net-tools isc-dhcp-client ntpdate \      openssh-server iproute2 iptables iputils-ping \      i2c-tools can-utils usbutils pciutils \      screen picocom \      vim nano # set root password echo -e "root\nroot" | chroot /mnt passwd # teardown chroot env umount /mnt/var/lib/apt/ umount /mnt/var/cache/apt chroot /mnt apt clean chroot /mnt apt autoclean reboot EOF chmod +x overlay/etc/init.d/S99boostrap-ubuntu.sh make buildroot_defconfig make -j8 }}} * generic aarch64 kernel Image and rootfs.cpio.gz will be in output/images 2. Use qemu to kick off a virtual aarch64 machine which will run the init script and create root filesystem on a virtual disk {{{#!bash apt install qemu-system-arm truncate -s $SIZE $IMG qemu-system-aarch64 -m 1G -M virt -cpu cortex-a57 -nographic -smp 1 -no-reboot \    -device virtio-net-device,netdev=eth0 -netdev user,id=eth0 \    -device virtio-blk-device,drive=hd0 -drive file=$IMG,if=none,format=raw,id=hd0 \    -append "console=ttyAMA0 ip=dhcp" \    -kernel output/images/Image \    -initrd output/images/rootfs.cpio.gz }}} * ubuntu.ext4 contains your rootfs - add desired changes to the setup script [=#debootstrap] === Creating Ubuntu rootfs using deboostrap A popular way to create an Ubuntu root filesystem is to use the {{{deboostrap}}} utility on a Debian or Ubuntu host. This tool provides a 2-stage install where the second stage is within a chroot environment using qemu. Gateworks uses a script to do this which you may find at http://github.com/Gateworks/ubuntu-rootfs Requirements: - Linux Ubuntu or Debian System with network connection and sudo permissions Important notes: * We set and use '''target''' and '''distro''' env variables in step 2 and use those env variables in the remaining steps to make this tutorial more version-agnostic. Please be aware of this and do not deviate from the steps unless or until you completely understand what you are doing. * These steps are not always exactly what we do in our script but give you an idea of how you would go about doing it yourself if you wanted to customize something Steps: 1. Install pre-requisites: {{{ #!bash sudo apt-get install qemu-user-static debootstrap binfmt-support }}} 2. Perform first stage install of minimal filesystem for {{{arm64}}} architecture: {{{#!bash distro=focal arch=arm64 target=${distro}-${arch} qemu_arch=aarch64 sudo debootstrap --arch=$arch --foreign $distro $target # copy qemu binary for the binfmt packages to find it and copy in resolv.conf from host sudo cp /usr/bin/qemu-${qemu_arch}-static $target/usr/bin }}} * See http://ports.ubuntu.com/ubuntu-ports/dists/ for a list of current Ubuntu releases: oe 20.04=focal (latest LTS) * this minimal rootfs is still missing some core packages and configuration before it can be booted. These steps are taken care of in a 2nd stage install within a chroot shell * the chroot shell below will provide network support (inherited from the host) 3. We now have a minimal Ubuntu rootfs - chroot to it and perform the 2nd stage install: {{{ #!bash sudo chroot $target # now we are in the chroot - setup env matching the distro above distro=focal export LANG=C # setup second stage /debootstrap/debootstrap --second-stage }}} * this is the most minimal rootfs we would recommend 4. (optional) add additional apt package repos: {{{ #!bash cat < /etc/apt/sources.list deb http://ports.ubuntu.com/ubuntu-ports $distro main restricted universe multiverse deb http://ports.ubuntu.com/ubuntu-ports $distro-updates main restricted universe multiverse deb http://ports.ubuntu.com/ubuntu-ports $distro-security main restricted universe multiverse EOT }}} * you may want to customize the above list, depending on your needs. See [#packages below] for more detail on Ubuntu package feeds 5. (optional) update package database and setup locales (do not skip this step if you are needing to install any packages for the steps below or otherwise) {{{ #!bash apt-get update apt-get -f install # fixup missing package dependencies apt-get install locales dialog dpkg-reconfigure locales }}} 6. Set hostname: {{{ #!bash echo ${distro}-$(uname -m) > /etc/hostname }}} 7. set a root passwd so you can login {{{ #!bash passwd }}} - or consider adding a user via {{{adduser}}}: {{{ #!bash adduser myuser usermod -a -G tty myuser # add to tty group for tty access usermod -a -G dialout myuser # add to dialout group for UART access usermod -a -G sudo myuser # add to sudo group for root access }}} 8. (optional) configure networking: - wired ethernet with DHCP on eth0 {{{#!bash apt-get install net-tools ifupdown cat <> /etc/network/interfaces allow-hotplug eth0 auto eth0 iface eth0 inet dhcp EOF }}} - or static IP: {{{#!bash apt-get install net-tools ifupdown cat <> /etc/network/interfaces allow-hotplug eth0 auto eth0 iface eth0 inet static address 192.168.1.1 netmask 255.255.255.0 gateway 192.168.1.254 EOF }}} - or wireless (requires ~3MB of additional packages): {{{ #!bash apt-get install wpasupplicant iw cat << EOF >> /etc/network/interfaces # Wireless interface auto wlan0 iface wlan0 inet dhcp wireless_mode managed wireless_essid any wpa-driver nl80211 wpa-conf /etc/wpa_supplicant.conf EOF wpa_passphrase >> /etc/wpa_supplicant.conf }}} 9. (optional) install some useful packages {{{ #!bash apt-get install openssh-server # ssh server for remote access apt-get install can-utils i2c-tools usbutils pciutils # cmdline tools for various hardware support }}} * Note that by default root ssh access is disabled for security. See [wiki:/ubuntu#SSHServer This link] for info on enabling it 10. Exit the chroot shell and remove files we no longer need {{{ #!bash exit sudo rm $target/usr/bin/qemu-$qemu_arch-static }}} At this point you have a directory containing a root filesystem (without kernel) and likely want to install it onto removable storage or the on-board FLASH of a target board. Some intermediate formats that are useful to keep around would be a tarball, perhaps an ext4 filesystem image, or a compressed disk image suitable for flashing in the U-Boot bootloader. To create a tarball which is the most flexible storage format and can be used for a variety of future installation uses: {{{#!bash sudo tar --keep-directory-symlink -cvJf focal-venice.tar.xz -C rootfs/ . }}} * '--numeric-owner' is required to store user/group as a number instead of a name, your specific use case may require this switch. * the '-C rootfs/' is required to eliminate the rootfs directory prefix * the sudo is needed to be able to read the root owned files * '--keep-directory-symlink' will preserve symbolic links To create an ext4 filesystem from the directory or tarball requires you choose a size for the filesystem. This size can be increased at runtime using {{{resize2fs}}} as long as the partition table has room for it to grow. The advantage of using an as small as possible size is that the time necessary to flash it onto storage is reduced to a minimum (when flashing you have to write the entire ext4 fs but when formatting or resizing it only has to write periodic markers to FLASH). For a given size (see SIZEMB variable below) you can create a rootfs with: {{{#!bash SIZEMB=1536 # 1.5GB - expandable later with resize2fs OUT=rootfs.ext4 # create a file of specific size truncate -s ${SIZEMB}M ${OUT} # format it as an ext4 filesystem mkfs.ext4 -q -F -L rootfs ${OUT} # mount it to a temporary mount point tmp_mnt=$(mktemp -d -p/tmp) mount ${OUT} ${tmp_mnt} # copy files to it cp -rup rootfs/* ${tmp_mnt} # and/or extract files from a tarball tar -C ${tmp_mnt} -xf linux-venice.tar.xz --keep-directory-symlink # unmount temporary mount point umount ${tmp_mnt} sync # compress it gzip -k -f ${OUT} }}} == Ubuntu Webmin A web GUI for system management: [wiki:webui Ubuntu Webmin] [[Image(Webmin_Logo.png,200px)]] [=#packages] == Ubuntu Packages == Ubuntu inherits its package management from Debian Linux using the 'apt' packaging system and 'deb' packages. The list of package feeds is in /etc/apt/sources.list: {{{ #!bash # cat rootfs/etc/apt/sources.list deb http://ports.ubuntu.com/ubuntu-ports vivid main deb http://ports.ubuntu.com/ubuntu-ports vivid universe }}} You can search for Ubuntu packages at https://launchpad.net/ubuntu. The search results will show what Ubuntu versions (by name) the package is available in and clicking on the resulting package will show information as to the package feed its contained in. The standard Ubuntu package feeds are located at http://ports.ubuntu.com/ubuntu-ports/ and you will find packages in the dist// directories. Ubuntu breaks up feeds into the following: * Main - Officially supported software. * Restricted - Supported software that is not available under a completely free license. * Universe - Community maintained software, i.e. not officially supported software. * Multiverse - Software that is not free. (meaning licensing) If you are trying to find out what package an application belongs to you have a few choices: 1. Use {{{dpkg -S}}} on your Ubuntu development host. For example to find the package that contains ifconfig: {{{ #!bash $ dpkg -S $(which ifconfig) net-tools: /sbin/ifconfig }}} * ifconfig is in /sbin/ifconfig and is part of the net-tools package * {{{dpkg -L net-tools}}} will show you everything else contained in that package 2. Use {{{apt-cache search}}}: {{{ #!bash $ apt-cache search ifconfig iproute2 - networking and traffic control tools net-tools - The NET-3 networking toolkit gnome-nettool - network information tool for GNOME inetutils-tools - base networking utilities (experimental package) libnet-ifconfig-wrapper-perl - multiplatform Perl wrapper for ifconfig moreutils - additional Unix utilities wmifinfo - Dockapp that shows information for all interfaces }}} 3. Googling the question 'what package contains ' Personal Package Archives (PPAs) are package feeds that are not part of Ubuntu and can be used by people to distribute their own personally built packages. To use a PPA you need to first add it to your repository list and update your package sources. Some additional useful apt command examples: * update package feeds: {{{#!bash apt-get update }}} * upgrade all installed packages to their latest versions: {{{#!bash apt-get upgrade }}} * show what version of a package is available (regardless of if its installed), for example bluez: {{{#!bash apt-cache show bluez }}} * clean out any old packages that have newer versions installed and no longer are dependencies of anything else installed: {{{#!bash apt-get autoremove }}} * clean out apt caches: {{{#!bash apt-get clean }}} * remove a package (leaves its configs), for example 'bluez': {{{#!bash apt-get remove bluez }}} * remove a package including any config files (as they normally don't get removed), for example 'bluez': {{{#!bash apt-get purge bluez }}} * show all available packages including version info: {{{#!bash apt list }}} * show all installed packages including version info: {{{#!bash apt list --installed }}} * show upgradable packages: {{{#!bash apt list --upgradable }}} References: * [https://help.ubuntu.com/community/Repositories/Ubuntu Ubuntu Software Repositories] * [http://askubuntu.com/questions/4983/what-are-ppas-and-how-do-i-use-them What are PPAs and how do I use them] [=#gateworks-packages] == Gateworks Packages Gateworks maintains a set of packages that are either custom Gateworks applications or packages that we patch or configure differently than those offered by the official Ubuntu package repositories. You can find these at https://launchpad.net/~gateworks-software/+archive/ubuntu/packages which you can add to your Ubuntu system by: * Add Gateworks PPA {{{#!bash sudo add-apt-repository ppa:gateworks-software/packages sudo apt-get update }}} * Prioritize Gateworks PPA to have higher priority than others {{{#!bash cat <<\EOF > /etc/apt/preferences.d/gateworks Package: * pin: release o=LP-PPA-gateworks-software-packages Pin-Priority: 1010 EOF }}} - Note that these steps are already done on the Gateworks prebuilt Ubuntu images Packages that Gateworks provides in this PPA include: * brcm-patchram - a userspace app needed to load firmware onto Broadcom USB chips such as that found on the GW5913 * gsc-update - a userspace app used to compute checksums of Gateworks System Controller firmware images and update firmware * gst-gateworks-apps - Example Gstreamer applications * gwsoc - a userspace app used to update firmware and configure GW16113 * hostapd-conf - a shell script that can be used to interactively create a config file for hostapd for Wireless AP's * openocd - an updated build of OpenOCD as they have not had a new release since 0.10 released in Jan 2017 * openssl - Ubuntu's openssl built with AFALG and Cryptodev support enabled [=#modem] == Modem Support Aleksander Morgado (​https://aleksander.es), a key developer behind the !ModemManager, libqmi, and libmbim projects that provide modem support on Ubuntu provides up-to-date Ubuntu PPA's for Ubuntu. See [wiki:wireless/modem#ubuntu modem#ubuntu] for more info on how to use these packages and how to retrieve the latest versions of them from his PPA [=#ssh] == SSH Server == The {{{openssh-server}}} package provides an ssh daemon suitable for secure shell (ssh) and secure copy (scp): {{{ #!bash apt-get install openssh-server }}} During development it may be useful to enable root ssh capability, which is disabled by default. To do this edit /etc/ssh/sshd_config, and: 1. comment out the following line: {{{ #!bash PermitRootLogin without-password }}} 2. Just below it, add the following line: {{{ #!bash PermitRootLogin yes }}} 3. Then reload SSH config: {{{ #!bash service ssh reload }}} [=#wireless] == Wireless == It helps to check if your wlan0 device is present before continuing with these steps, this can be done by: {{{#!bash ls /sys/class/net/ }}} is wlan0 in this directory? If so proceed, if not consult [http://trac.gateworks.com/wiki/wireless/wifi wifi] wiki. [=#wireless-ap] === Access Point (AP) === These instructions below are for creating a wireless Access Point (AP) that will allow nearby client connections. 1. Install required packages {{{#!bash apt-get update apt-get install iw hostapd linux-firmware }}} 1. Download the Gateworks {{{hostapd-conf}}} script from our Yocto BSP, this script will produce a 'basic' configuration file to set up your AP: {{{#!bash wget https://raw.githubusercontent.com/Gateworks/meta-gateworks/master/recipes-support/hostapd-conf/hostapd-conf/hostapd-conf chmod +x ./hostapd-conf }}} 1. Run the script with your parameters {{{#!bash # See usage ./hostapd-conf # See available channel information for device ./hostapd-conf wlan0 ssid-name # parses information from 'iw list' command # Enter full AP configuration ./hostapd-conf wlan0 test-ssid 161 VHT80 }}} 1. Run {{{hostapd}}} with your configuration file {{{#!bash hostapd -B hostapd-phy0.conf # use -dd flag for more debug output # "wlan0: interface state UNINITIALIZED->HT_SCAN" shows AP has been set up }}} Note that the {{{hostapd-phy0.conf}}} file created for you via the {{{hostapd-conf}}} script is meant to be a starting point and does not allow you to create every possible combination of configurations. For more information on the {{{hostapd.conf}}} file and its options, see the [https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf hostapd.conf documentation]. [=#wireless-client] === Client using wpa_supplicant === These instructions below are for creating a wireless client that will connect to a nearby access point. 1. Install required packages: {{{#!bash apt-get update apt-get install iw wpasupplicant udhcpc }}} 1. Edit {{{/etc/network/interfaces}}} and edit/add the following to configure wlan0 on boot wpa_supplicant: {{{#!bash cat << EOF >> /etc/network/interfaces # Wireless interface auto wlan0 iface wlan0 inet dhcp wireless_mode managed wireless_essid any wpa-driver nl80211 wpa-conf /etc/wpa_supplicant.conf EOF }}} 1. Create WPA Supplicant Configuration File at {{{/etc/wpa_supplicant.conf}}} using the {{{wpa_passphrase}}} application (see the man page on wpa_supplicant.conf if you need any special configurations): {{{#!bash wpa_passphrase >> /etc/wpa_supplicant.conf }}} 1. Sync and power cycle the board {{{#!bash sync }}} Troubleshooting: * Make sure you only have one wpa_supplicant running via {{{ps -ef | grep wpa_supplicant}}} * To scan for available access points in range you can use the iw tool: {{{#!bash iw dev wlan0 scan # scan for AP's }}} * To manually connect to wireless if auto connection is not working: While the above will configure wireless Client mode on bootup, if you want to start it manually you can do so by manually starting/re-starting wpa_supplicant (ifup will do this for you on bootup if configured in /etc/network/interfaces): {{{#!bash ifconfig wlan0 up killall wpa_supplicant wpa_supplicant -i wlan0 -D nl80211 -c /etc/wpa_supplicant.conf -B # manage wireless client udhcpc -i wlan0 # obtain dhcp lease }}} [=#predictable-interface-names] == Predictable Interface Names (systemd/udev) == The Linux kernel creates Ethernet network interfaces named 'eth' where starts at 0 and increments for each device registered by various drivers. The kernel makes no guarantee that these names remain constant across kernel versions or even power cycles. It is not uncommon for example for USB network interfaces to get registered in an inconsistent fashion between power cycles. It is also not uncommon for a kernel change (ie making a built-in driver be a module instead) to cause interface names move around due to changes in the registration order. To combat this uncertainty a feature referred to as 'Predictable Interface Names' is implemented in Linux distros which use {{{systemd}}} and {{{udev}}}. Specifically this feature has been in {{{udevd}}} since v197. In this case the network interfaces are re-named based on udev rules according to their bus topology. For example under this scheme a PCI based Ethernet network interface on bus 5, slot 0, function 1 would be names 'enp5s0f1'. The best documentation for the naming scheme appears to be the [https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-net_id.c#L20 udev code comments] Predictable interface names is enabled by default on systems using {{{systemd}}}/{{{udev}}} however you can disable it in a couple of ways: * Pass in a kernel command-line parameter of {{{net.ifnames=0}}}. Note that this is 'not' a kernel feature (thus is independent of what kernel version you are using) but the {{{systemd}}}/{{{udev}}} components that implement this feature look for that on the command-line. (default on Gateworks) * Remove {{{/lib/systemd/network/99-default.link}}} from the root filesystem. Alternatively you can also create your own {{{link}}} files to name interfaces to your liking. A {{{link}}} file defines matching criteria and link criteria for naming. You can use 'udevadm info ' to obtain details that {{{udev}}} knows about devices (ie 'udevadm info /sys/class/net/eth0' or /udevadm info /dev/ttyUSB0'). Your link files should be placed in {{{/etc/systemd/network}}} and should sort before {{{99-default.link}}} from {{{/lib/systemd/network}}}. An example to force a wlan0 name by MAC address c0:ee:40:99: {{{ root@gw7301:/lib/systemd/network# cat 90-wlan0.link [Match] MACAddress=c0:ee:40:99 [Link] Name=wlan0 }}} References: - [https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ Predictable Network Interfaces] - [https://www.freedesktop.org/software/systemd/man/systemd.link.html systemd link file notation] - [https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-net_id.c#L20 udev code documenting naming convention] - [https://major.io/2016/01/20/tinkering-with-systemds-predictable-network-names/ Good Blog article on creating your own link files] - [https://major.io/2015/08/21/understanding-systemds-predictable-network-device-names/ Good Blog article about Predictive Interface Names] - net/core/dev.c:dev_change_name - changes name of device by passing strings like "eth%d" [=#network] == Network Configuration There are various resources on the Internet dealing with Ubuntu network interface configuration which we don't intend to compete with here. In general: * See {{{/etc/network/interfaces}}} for the default network interface configuration * See {{{/etc/dhcp/dhclient.conf}}} for the default DHCP client configuration * Typically the Gateworks prebuilt root filesystems will configure networking to bring up {{{eth0}}} by default using {{{dhcp}}} for network configuration with a 10 second timeout. This is done by setting 'timeout 10;' in {{{/etc/dhcp/dhclient.conf}}}: {{{#!bash sed -i 's/^timeout.*/timeout 10;/' /etc/dhcp/dhclient.conf }}} Note that DHCP only retries every 5 minutes to give an IP address per the man pages: [https://manpages.ubuntu.com/manpages/trusty/man5/dhclient.conf.5.html] [=#time] == Network Time Protocol (NTP) Configuration Network Time can set your system time based on network time servers: * bionic: {{{#!bash apt-get install chrony }}} * xenial: {{{#!bash apt-get install ntp }}} [=#rtc] == Real Time Clock (RTC) Configuration System Time can be set from a Real Time Clock such as the DS1672 that the Gateworks System Controller emulates but this does not seem to work on modern Ubuntu out of the box. While the {{{util-linux}}} package that provides {{{hwclock}}} installs a service {{{/etc/init.d/hwclock.sh}}} it won't run because {{{systemd}}} is installed and the service is masked. You can work around this by installing a hwclock.service: {{{#!bash cat << EOF > /etc/systemd/system/hwclock.service [Unit] Description=Hardware clock synchronization [Service] Type=oneshot ExecStart=/sbin/hwclock --hctosys --utc --adjfile=/etc/adjtime ExecStop=/sbin/hwclock --systohc --utc --adjfile=/etc/adjtime [Install] WantedBy=multi-user.target EOF systemctl enable hwclock }}} [=#watchdog] == Watchdog The standard Linux watchdog daemon can be installed on ubuntu and configured. Note that these steps are already done for you when using the Gateworks pre-built Ubuntu based images: * install package {{{#!bash # install apt-get install watchdog }}} * create conf file: {{{#!bash cat << EOF > /etc/watchdog.conf watchdog-device = /dev/watchdog realtime = yes priority = 1 interval = 5 watchdog-timeout = 30 EOF }}} [=#hello-world.c] == Cross compiling example If you wish to compile applications on a development host intended to run on a target with a different architecture (ie you have an x86 host, and an arm64 target like Venice or Newport) you can use Ubuntu's cross toolchain which consits of a gcc cross-compiler, libc, and binutils. Example: * cross compile for ARM64 (Venice / Newport) on X86 Ubuntu host: {{{#!bash # install Ubuntu cross-build package sudo apt update sudo apt install crossbuild-essential-arm64 # installs gcc as well as binutils and libs aarch64-linux-gnu-gcc -v # see gcc version if interested # build a simple app, using shared libraries cat << EOF >> helloworld.c #include int main (int argc, char** argv) { printf("Hello World\n"); return 0; } EOF aarch64-linux-gnu-gcc helloworld.c -o helloworld file helloworld # shows ELF 64-bit LSB shared object, ARM aarch64, dynamically linked with interpreter /lib/ld-linux-aarch64.so.1 aarch64-linux-gnu-objdump -x helloworld | grep NEEDED # show libs needed on target }}} - this was tested on both an Ubuntu bionic dev host (providing gcc-v7.5) as well as an Ubuntu focal dev host (providing gcc-v9.4.0) * cross compile for ARM32 (Ventana) on X86 Ubuntu host: {{{#!bash # install Ubuntu cross-build package sudo apt update sudo apt install crossbuild-essential-armel # installs gcc as well as binutils and libs arm-linux-gnueabi-gcc -v # see gcc version if interested # build a simple app, using shared libraries cat << EOF >> helloworld.c #include int main (int argc, char** argv) { printf("Hello World\n"); return 0; } EOF arm-linux-gnueabi-gcc helloworld.c -o helloworld file helloworld # shows ELF 32-bit LSB ARM EABI5v1 shared object, dynamically linked with interpreter /lib/ld-linux.so.3 arm-linux-gnueabi-objdump -x helloworld | grep NEEDED # show libs needed on target }}} == Native compiling example While typically not as fast as cross-compiling on a higher end processing Linux development host it can be simple to compile ANSI-C code natively on a Gateworks board running an Ubuntu OS. To natively compile a .c file on a Newport board using Ubuntu, follow the instructions: * First, install build-essential {{{ apt-get update apt-get install build-essential }}} * Create your C application with the editor of your choice (vi, vim, nano, sublime etc). Here we just use {{{cat}}} so you can cut-and-paste: {{{#!bash #include int main(void) { printf("hello, world\n"); } }}} * Compile the file: {{{#!bash ~# gcc -o hello helloworld.c }}} * Run the file {{{#!bash ~# ./hello hello, world }}}