Arduino:Примеры/ExpandingYúndiskspace

Материал из Онлайн справочника
Версия от 12:34, 8 июля 2023; EducationBot (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Как расширить дисковое пространство на Yun[1]

Операционная система OpenWrt-Yun на базе GNU/Linux, будучи установленной на Yun, занимает примерно 9 из 16 мегабайт доступной Flash-памяти. Это значит, что если вы установите слишком много приложений и программных пакетов, места вам будет категорически не хватать.

Впрочем, дисковое пространство на Arduino Yun можно увеличить, подключив к плате SD-карту и настроив ее таким образом, чтобы она стала вашей новой Linux’овой файловой системой. После этого все, что вы будете делать на Linux-стороне Yun , будет храниться на этой SD-карте.

Процедура настройки не сложна, но все же требует базовых знаний в области Linux. Поэтому мы автоматизировали все шаги и сделали соответствующий скетч, использующий библиотеку Bridge. Так что просто вставьте карту и следуйте интерактивным инструкциям в Serial Monitor.

Скетч разделит SD-карту на две части. Первая будет отформатирована под FAT32 и с ней можно будет работать с любого компьютера, т.е. ею можно будет пользоваться для того, чтобы обмениваться файлами между компьютером и Yun. Вторая часть будет содержать файловую систему Yun. Любая установленная вами программа и любой конфигурационный файл будет скопирован на SD-карту, поэтому вам не придется ничего переустанавливать и перенастраивать – Yun останется такой же, как прежде, просто дискового пространства у нее будет побольше. Впрочем, имейте в виду, что если вы используете Windows или Mac, то вторая часть для вашего компьютера будет недоступна.

Подготовка

Подключите вашу Yun к компьютеру и подождите около минуты. Убедитесь, что Yun подключена к интернету, потому что процедура потребует дополнительного ПО. Отключите от Yun все девайсы, а затем вставьте SD-карту.

Внимание! Ваша SD-карта будет отформатирована, поэтому вы потеряете все записанные на нее данные. Поэтому перед тем, как расширять дисковое пространство на Yun, убедитесь, что вся необходимая информация скопирована в другое, более безопасное место.

Загрузите ZIP-файл, содержащий скетч, распакуйте его и скопируйте содержимое в папку скетчей для Arduino. Откройте среду разработки Arduino и загрузите скетч YunDiskSpaceExpander.

Вот ссылка на ZIP-файл.

/*

Расширение дискового пространства на Yun
  
Требуются:
* Карта формата micro SD
* Подсоединение к интернету

Этот скетч конфигурирует SD-карту, чтобы расширить дисковое пространство Arduino Yun.
Загрузите его, откройте Serial Monitor и следуйте интерактивным инструкциям.

Внимание! Ваша SD-карта будет отформатирована, поэтому вы потеряете все имеющиеся на ней файлы.
Поэтому, перед тем, как расширять дисковое пространство на Yun,
сделайте бэкап этих файлов.

Создан в апреле 2014 
Федерико Фиссоре (Federico Fissore) и Федерико Ванзати (Federico Vanzati).

Этот код не защищен авторским правом.

http://arduino.cc/en/Tutorial/ExtendingYunDiskSpace

*/

#include <Process.h>

#define DEBUG 0
#define SUCCESSFUL_EXIT_CODE 0

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.print(F("This sketch will format your micro SD card and use it as additional disk space for your Arduino Yun.\nPlease ensure you have ONLY your micro SD card plugged in: no pen drives, hard drives or whatever.\nDo you wish to proceed (yes/no)?"));  //  "Этот скетч отформатирует вашу SD-карту и воспользуется ею, как дополнительным дисковым пространством для Yun.\nПожалуйста, убедитесь, что в Yun вставлена только SD-карта и ничего более – ни флэшек, ни жестких дисков, ни т.п."
  expectYesBeforeProceeding();

  Serial.println(F("\nStarting Bridge..."));  //  "Запускаем Bridge..."

  Bridge.begin();

  haltIfSDAlreadyOnOverlay();
  
  haltIfInternalFlashIsFull();

  haltIfSDCardIsNotPresent();

  installSoftware();

  partitionAndFormatSDCard();

  createArduinoFolder();

  copySystemFilesFromYunToSD();

  enableExtRoot();

  Serial.print(F("\nWe are done! Yeah! Now press the YUN RST button to apply the changes."));  //  "Готово! Отлично! Теперь нажмите на кнопку YUN RST, чтобы изменения вступили в силу."
}

void loop() {
  // Это превратит скетч в пример «Доступ к терминалу Linux через Serial Monitor»
  if (Serial.available()) {
    char c = (char)Serial.read();
    Serial1.write(c);
  }
  if (Serial1.available()) {
    char c = (char)Serial1.read();
    Serial.write(c);
  }
}

void halt() {
  Serial.flush();
  while (true);
}

void expectYesBeforeProceeding() {
  Serial.flush();

  while (!Serial.available());

  String answer = Serial.readStringUntil('\n');

  Serial.print(F(" "));
  Serial.println(answer);
  if (answer != "yes") {
    Serial.println(F("\nGoodbye"));  //  "Пока!"
    halt();
  }
}

int readPartitionSize() {
  int partitionSize = 0;
  while (!partitionSize)
  {
    Serial.print(F("Enter the size of the data partition in MB: "));  //  "Введите размер для разбиения дискового пространства (в мегабайтах): "
    while (Serial.available() == 0);

    String answer = Serial.readStringUntil('\n');
    partitionSize = answer.toInt();
    Serial.println(partitionSize);
    if (!partitionSize)
      Serial.println(F("Invalid input, retry"));  //  "Неправильно, введите снова"
  }
  return partitionSize;
}

void debugProcess(Process p) {
  #if DEBUG == 1
  while (p.running());

  while (p.available() > 0) {
    char c = p.read();
    Serial.print(c);
  }
  Serial.flush();
  #endif
}

void haltIfSDAlreadyOnOverlay() {
  Process grep;

  grep.runShellCommand(F("mount | grep ^/dev/sda | grep 'on /overlay'"));
  String output = grep.readString();
  if (output != "") {
    Serial.println(F("\nMicro SD card is already used as additional Arduino Yun disk space. Nothing to do."));  //  "\nSD-карта уже используется в качестве дополнительного дискового пространства для Yun."
    halt();
  }
}

void haltIfSDCardIsNotPresent() {
  Process ls;
  int exitCode = ls.runShellCommand("ls /mnt/sda1");

  if (exitCode != 0) {
    Serial.println(F("\nThe micro SD card is not available"));  //  "\nSD-карта недоступна"
    halt();
  }
}

void haltIfInternalFlashIsFull() {
  Process awk;

  awk.runShellCommand(F("df / | awk '/rootfs/ {print $4}'"));
  int output = awk.parseInt();
  if (output < 1000) {
    Serial.println(F("\nYou don't have enough disk space to install the utility software. You need to free at least 1MB of Flash memory.\nRetry!"));  //  "У вас недостаточно дискового пространства для установки утилиты. Нужно освободить как минимум один мегабайт Flash-памяти.\nПопробуйте еще раз!"
    halt();
  }
}

void installSoftware() {
  Serial.print(F("\nReady to install utility software. Please ensure your Arduino Yun is connected to internet.\nReady to proceed (yes/no)?"));  //  "К установке утилиты все готово. Пожалуйста, убедитесь, что Arduino Yun подключена к интернету.\nГотовы продолжать (да/нет)?"
  expectYesBeforeProceeding();

  Serial.println(F("Updating software list..."));  //  "Обновление списка ПО..."

  Process opkg;

  // Обновляем список пакетов
  int exitCode = opkg.runShellCommand("opkg update");
  // если с кодом завершения (exitCode) процесса никаких проблем нет, это значит, что пакет установлен успешно:
  if (exitCode != SUCCESSFUL_EXIT_CODE) {
    Serial.println(F("err. with opkg, check internet connection"));  //  "Ошибка с opkg, проверьте интернет-соединение"
    debugProcess(opkg);
    halt();
  }
  Serial.println(F("Software list updated. Installing software (this will take a while)..."));  //  "Список ПО обновлен. Установка ПО (этот процесс займет какое-то время)..."

  // Устанавливаем утилиту для форматирования в EXT4:
  exitCode = opkg.runShellCommand(F("opkg install e2fsprogs mkdosfs fdisk rsync"));
  if (exitCode != SUCCESSFUL_EXIT_CODE) {
    Serial.println(F("err. installing e2fsprogs mkdosfs fdisk"));  //  "Ошибка в установке e2fsprogs mkdosfs fdisk"
    debugProcess(opkg);
    halt();
  }
  Serial.println(F("e2fsprogs mkdosfs fdisk rsync installed"));  //  " e2fsprogs mkdosfs fdisk rsync установлена"
}

void partitionAndFormatSDCard() {
  Serial.print(F("\nProceed with partitioning micro SD card (yes/no)?"));  //  "\nПродолжать разбиение SD-карты? (да/нет)?"
  expectYesBeforeProceeding();

  unmount();

  Process format;

  // Очищаем таблицу разбиения SD-карты:
  format.runShellCommand("dd if=/dev/zero of=/dev/sda bs=4096 count=10");
  debugProcess(format);

  // Запускаем процесс разбиения и создаем первую часть:
  int dataPartitionSize = readPartitionSize();

  Serial.println(F("Partitioning (this will take a while)..."));  //  "Разбиение SD-карты (этот процесс займет какое-то время)..."
  String firstPartition = "(echo n; echo p; echo 1; echo; echo +";
  firstPartition += dataPartitionSize;
  firstPartition += "M; echo w) | fdisk /dev/sda";
  format.runShellCommand(firstPartition);
  debugProcess(format);

  unmount();

  // Создаем вторую часть:
  format.runShellCommand(F("(echo n; echo p; echo 2; echo; echo; echo w) | fdisk /dev/sda"));
  debugProcess(format);

  unmount();

  // Уточняем, что форматировать нужно в формате FAT32:
  format.runShellCommand(F("(echo t; echo 1; echo c; echo w) | fdisk /dev/sda"));

  unmount();

  delay(5000);

  unmount();

  // Форматируем первую часть в FAT32:
  int exitCode = format.runShellCommand(F("mkfs.vfat /dev/sda1"));
  debugProcess(format);
  if (exitCode != SUCCESSFUL_EXIT_CODE) {
    Serial.println(F("\nerr. formatting to FAT32"));  //  "\nОшибка при форматировании в FAT32"
    halt();
  }
  delay(100);

  // Форматируем вторую часть в Linux EXT4:
  exitCode = format.runShellCommand(F("mkfs.ext4 /dev/sda2"));
  debugProcess(format);
  if (exitCode != SUCCESSFUL_EXIT_CODE) {
    Serial.println(F("\nerr. formatting to EXT4"));  //  "\nОшибка при форматировании в EXT4"
    halt();
  }

  Serial.println(F("Micro SD card correctly partitioned"));  // "Разбиение SD-карты прошло успешно"
}

void createArduinoFolder() {
  Serial.print(F("\nCreating 'arduino' folder structure..."));  //  "Создание папки «arduino»"
  Process folder;

  folder.runShellCommand(F("mkdir -p /mnt/sda1"));
  folder.runShellCommand(F("mount /dev/sda1 /mnt/sda1"));
  folder.runShellCommand(F("mkdir -p /mnt/sda1/arduino/www"));

  unmount();
}

void copySystemFilesFromYunToSD() {
  Serial.print(F("\nCopying files from Arduino Yun flash to micro SD card..."));  //  "Копирование файлов с flash-памяти Arduino Yun на SD-карту"
  Process copy;

  copy.runShellCommand(F("mkdir -p /mnt/sda2"));
  copy.runShellCommand(F("mount /dev/sda2 /mnt/sda2"));
  copy.runShellCommand(F("rsync -a --exclude=/mnt/ --exclude=/www/sd /overlay/ /mnt/sda2/"));

  unmount();
}

void unmount() {
  Process format;
  format.runShellCommand(F("umount /dev/sda?"));
  debugProcess(format);
  format.runShellCommand(F("rm -rf /mnt/sda?"));
  debugProcess(format);
}

void enableExtRoot() {
  Serial.print(F("\nEnabling micro SD as additional disk space... "));  //  "Активация SD-карты в качестве дополнительного дискового пространства..."

  Process fstab;

  fstab.runShellCommand(F("uci add fstab mount"));
  fstab.runShellCommand(F("uci set fstab.@mount[0].target=/overlay"));
  fstab.runShellCommand(F("uci set fstab.@mount[0].device=/dev/sda2"));
  fstab.runShellCommand(F("uci set fstab.@mount[0].fstype=ext4"));
  fstab.runShellCommand(F("uci set fstab.@mount[0].enabled=1"));
  fstab.runShellCommand(F("uci set fstab.@mount[0].enabled_fsck=0"));
  fstab.runShellCommand(F("uci set fstab.@mount[0].options=rw,sync,noatime,nodiratime"));
  fstab.runShellCommand(F("uci commit"));

  Serial.println(F("enabled"));  //  "Активация завершена"
}

Откройте Serial Monitor и обязательно проверьте, выбран ли в выпадающем меню пункт Newline.

Старт

Когда вы откроете Serial Monitor, появится сообщение, которое известит вас о том, что от Yun нужно отключить все другие дисковые устройства, кроме SD-карты. Если готовы продолжать, напишите «yes» и нажмите Enter.

Установка ПО

Для начала устанавливаем программное обеспечение, необходимое для форматирования SD-карты. Перед тем, как напечатать «yes», убедитесь, что Yun подключена к интернету, иначе установка будет неудачной.

Форматирование SD-карты

Теперь, когда необходимое ПО корректно установлено, печатаем «yes» и жмем Enter, чтобы начать форматирование SD-карты.

Уточняем размер первой части SD-карты – той, которую выбудете использовать для обмена файлами с компьютером. Оставшаяся часть будет отведена под файловую систему Linux. В данном примере мы используем 2-гигабайтную SD-карту, а под первую часть отводим 700 Мб. Оставшиеся 1,3 Гб приютят у себя Linux.

Когда все будет готово, все конфигурационные и прочие файлы, хранящиеся во внутренней flash-памяти, будут скопированы на вторую часть SD-карты. Далее, чтобы все изменения вступили в силу, Yun нужно перезагрузить. Для этого нажмите на кнопку YUN RST (она располагается недалеко от светодиодов).

Скетч продолжит показывать оболочку Yun Linux, а на экран будет выводиться множество сообщений, оповещающих о загрузке Yun. Когда она закончится, впишите это:

df -h / /mnt/sda1

В ответ вы должны получить что-то вроде этого:

Filesystem              Size    Used Available Use% Mounted on
rootfs                  1.2G    51.7M   1.0G   5% /
/dev/sda1               698.6M  12.0K   698.6M   0% /mnt/sda1

Как видите, теперь нам доступен один гигабайт свободного дискового пространства. В самой OpenWrt оно будет называться extroot. Более подробную информацию можно найти на сайте OpenWrt.

См.также

Внешние ссылки