From 5ce1b05bacf35e3e93ba50a59ff6aca892713ea3 Mon Sep 17 00:00:00 2001
From: r007
Date: Wed, 14 Oct 2026 21:36:43 +0400
Subject: [PATCH] Update Russian translation of the Embedded Rust training
materials
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Revised introductory text in 01_intro.md for clarity and consistency.
- Updated hardware port description in 02_1_hardware.md to specify the correct directory.
- Changed terminology from "набор инструментов" to "тулчейн" in 02_2_software.md for accuracy.
- Clarified repository instructions in 02_3_repository.md and fixed cloning command.
- Enhanced explanations regarding project setup and error messages in 02_4_hello_board.md.
- Improved descriptions of build tools and dependencies in 03_1_project_orga.md and 03_2_cargo_generate.md.
- Adjusted HTTP client and server instructions for better understanding in 03_3_2_http_client.md and 03_4_http_server.md.
- Added clarity to MQTT functionality and configuration in 03_5_1_mqtt.md and 03_5_2_mqtt.md.
- Enhanced I2C driver explanations in 04_3_2_i2c.md and 04_3_3_i2c.md.
- Clarified interrupt handling instructions in 04_4_2_interrupts.md and 04_4_3_interrupts.md.
- Updated GPIO output descriptions in 05_reference.md for better technical accuracy.
---
CONTRIBUTING.md | 11 +-
comprehensive-rust/po/ru.po | 178 +++++++++---------
discovery-mb2/src/01-background/README.md | 4 +-
discovery-mb2/src/03-setup/IDE.md | 2 +-
discovery-mb2/src/03-setup/README.md | 2 +-
discovery-mb2/src/03-setup/linux.md | 2 +-
discovery-mb2/src/03-setup/verify.md | 2 +-
.../src/04-meet-your-hardware/microbit-v2.md | 4 +-
.../src/04-meet-your-hardware/terminology.md | 2 +-
.../src/05-meet-your-software/README.md | 6 +-
.../src/05-meet-your-software/build-it.md | 2 +-
.../src/05-meet-your-software/debug-it.md | 8 +-
.../05-meet-your-software/embedded-setup.md | 2 +-
.../src/05-meet-your-software/light-it-up.md | 10 +-
discovery-mb2/src/06-hello-world/README.md | 12 +-
.../src/06-hello-world/board-support-crate.md | 2 +-
.../src/06-hello-world/portability.md | 2 +-
discovery-mb2/src/06-hello-world/toggle-it.md | 2 +-
discovery-mb2/src/07-led-roulette/README.md | 2 +-
.../src/07-led-roulette/my-solution.md | 2 +-
.../src/08-inputs-and-outputs/README.md | 8 +-
discovery-mb2/src/09-registers/README.md | 12 +-
discovery-mb2/src/09-registers/rtrm.md | 14 +-
.../spooky-action-at-a-distance.md | 2 +-
discovery-mb2/src/09-registers/src/lib.rs | 2 +-
discovery-mb2/src/10-serial-port/README.md | 2 +-
.../src/11-uart/send-a-single-byte.md | 2 +-
.../src/12-i2c/read-a-single-register.md | 2 +-
discovery-mb2/src/15-interrupts/README.md | 4 +-
.../src/15-interrupts/addendum-pwm.md | 2 +-
.../src/15-interrupts/my-solution.md | 2 +-
.../nvic-and-interrupt-priority.md | 8 +-
discovery-mb2/src/15-interrupts/src/main.rs | 13 +-
.../src/15-interrupts/the-mb2-speaker.md | 2 +-
.../waiting-to-be-interrupted.md | 2 +-
discovery-mb2/src/16-snake-game/controls.md | 4 +-
discovery-mb2/src/16-snake-game/game-logic.md | 2 +-
discovery-mb2/src/README.md | 2 +-
.../1-general-troubleshooting/README.md | 2 +-
discovery-mb2/src/explore.md | 8 +-
embedded-book/src/SUMMARY.md | 2 +-
embedded-book/src/appendix/glossary.md | 2 +-
embedded-book/src/c-tips/index.md | 16 +-
embedded-book/src/collections/index.md | 6 +-
embedded-book/src/concurrency/index.md | 6 +-
.../src/design-patterns/hal/predictability.md | 2 +-
.../src/interoperability/c-with-rust.md | 4 +-
embedded-book/src/interoperability/index.md | 4 +-
.../src/interoperability/rust-with-c.md | 6 +-
embedded-book/src/intro/hardware.md | 2 +-
embedded-book/src/intro/index.md | 2 +-
embedded-book/src/intro/install.md | 2 +-
embedded-book/src/intro/no-std.md | 2 +-
embedded-book/src/intro/tooling.md | 2 +-
.../src/peripherals/a-first-attempt.md | 4 +-
embedded-book/src/peripherals/borrowck.md | 6 +-
embedded-book/src/peripherals/index.md | 4 +-
embedded-book/src/peripherals/singletons.md | 12 +-
embedded-book/src/portability/index.md | 2 +-
embedded-book/src/start/exceptions.md | 6 +-
embedded-book/src/start/hardware.md | 12 +-
embedded-book/src/start/interrupts.md | 2 +-
embedded-book/src/start/panicking.md | 6 +-
embedded-book/src/start/qemu.md | 14 +-
embedded-book/src/start/registers.md | 6 +-
embedded-book/src/start/semihosting.md | 6 +-
.../src/static-guarantees/design-contracts.md | 4 +-
.../src/static-guarantees/state-machines.md | 2 +-
.../zero-cost-abstractions.md | 2 +-
embedded-book/src/unsorted/speed-vs-size.md | 4 +-
esp32-book/src/SUMMARY.md | 2 +-
.../src/bluetooth/trouble/ble-module.md | 4 +-
.../bluetooth/trouble/running-ble-stack.md | 2 +-
esp32-book/src/buzzer/active-beep.md | 2 +-
esp32-book/src/buzzer/play-songs/code.md | 2 +-
esp32-book/src/buzzer/play-songs/index.md | 2 +-
.../src/core-concepts/adc/adc-in-esp32.md | 4 +-
esp32-book/src/core-concepts/adc/index.md | 2 +-
esp32-book/src/core-concepts/pwm/index.md | 6 +-
esp32-book/src/core-concepts/pwm/mcpwm.md | 2 +-
.../src/core-concepts/voltage-divider.md | 12 +-
esp32-book/src/e-ink/draw-text.md | 6 +-
esp32-book/src/esp32-intro/esp32-family.md | 2 +-
esp32-book/src/help.md | 2 +-
esp32-book/src/index.md | 4 +-
esp32-book/src/lcd/index.md | 2 +-
.../src/lcd/lcd-custom-char-generator.md | 2 +-
esp32-book/src/lcd/multi-custom-gen.md | 4 +-
esp32-book/src/ldr/how-it-works.md | 12 +-
esp32-book/src/ldr/led/index.md | 2 +-
esp32-book/src/led/index.md | 4 +-
esp32-book/src/oled/draw-image/bitmap.md | 4 +-
.../src/ratatui/hello-rust/mousefood.md | 2 +-
esp32-book/src/rfid/access-bits-calculator.md | 28 +--
esp32-book/src/rfid/access-bits.md | 2 +-
esp32-book/src/rfid/change-auth-key.md | 2 +-
esp32-book/src/rfid/index.md | 2 +-
esp32-book/src/sdcard/index.md | 4 +-
esp32-book/src/sdcard/read-sdcard.md | 4 +-
esp32-book/src/servo/ledc.md | 2 +-
esp32-book/src/tft-display/draw-text.md | 2 +-
esp32-book/src/thermistor/esp32-non-linear.md | 2 +-
esp32-book/src/thermistor/index.md | 2 +-
esp32-book/src/thermistor/non-linear.md | 10 +-
esp32-book/src/thermistor/oled/index.md | 4 +-
esp32-book/src/thermistor/steinhart.md | 12 +-
esp32-book/src/ultrasonic/how-it-works.md | 2 +-
.../src/wifi/embassy/async-access-website.md | 2 +-
.../src/wifi/embassy/connecting-wifi.md | 2 +-
esp32-book/src/wifi/led/index.md | 2 +-
.../wifi/web-server/exposing-to-internet.md | 2 +-
esp32-book/src/wifi/web-server/index.md | 2 +-
.../src/wifi/web-server/serve-website.md | 8 +-
esp32-book/src/wifi/web-server/wifi.md | 2 +-
.../application/project-overview.md | 2 +-
.../training-ru/application/project-setup.md | 10 +-
.../application/publishing-data.md | 4 +-
.../application/reading-sensor-data.md | 8 +-
.../application/wifi-connectivity.md | 12 +-
.../application/wifi-provisioning.md | 4 +-
no-std-training/training-ru/introduction.md | 6 +-
no-std-training/training-ru/prerequisites.md | 6 +-
pico-pico/src/SUMMARY.md | 8 +-
pico-pico/src/abstraction-layers.md | 8 +-
pico-pico/src/additional-hardware.md | 4 +-
.../src/async-embedded-rust/introduction.md | 2 +-
pico-pico/src/buzzer/active-beep.md | 12 +-
pico-pico/src/buzzer/beep.md | 10 +-
pico-pico/src/buzzer/circuit.md | 8 +-
pico-pico/src/buzzer/intro.md | 42 ++---
pico-pico/src/buzzer/play-songs/code.md | 8 +-
pico-pico/src/buzzer/play-songs/index.md | 12 +-
.../src/buzzer/play-songs/music-module.md | 2 +-
pico-pico/src/components.md | 2 +-
.../src/core-concepts/basics/breadboard.md | 4 +-
.../src/core-concepts/pwm/basic-concepts.md | 16 +-
.../pwm/manual-calculate-top-divider.md | 2 +-
.../src/core-concepts/pwm/period-frequency.md | 2 +-
.../src/core-concepts/pwm/pwm-in-rp2350.md | 2 +-
pico-pico/src/core-concepts/pwm/simulation.md | 10 +-
.../core-concepts/pwm/top-divider-rp2350.md | 2 +-
.../src/core-concepts/voltage-divider.md | 2 +-
pico-pico/src/debugging/pico-debug-probe.md | 6 +-
pico-pico/src/help.md | 2 +-
pico-pico/src/i2c/i2c-and-rust.md | 4 +-
pico-pico/src/i2c/i2c-embassy-rp-hal.md | 4 +-
pico-pico/src/i2c/index.md | 22 +--
pico-pico/src/i2c/rp2350-pico-i2c.md | 4 +-
pico-pico/src/index.md | 2 +-
.../src/lcd-display/display-custom-chars.md | 4 +-
pico-pico/src/led/pwm-dimming/embassy.md | 2 +-
pico-pico/src/led/pwm-dimming/index.md | 4 +-
pico-pico/src/led/pwm-dimming/simulation.md | 6 +-
pico-pico/src/max7219/code-led-matrix.md | 2 +-
pico-pico/src/oled/crates.md | 6 +-
pico-pico/src/oled/hello-oled-embassy.md | 2 +-
pico-pico/src/rfid/uid-led.md | 4 +-
pico-pico/src/servo/code-using-embassy-rp.md | 18 +-
pico-pico/src/servo/code-using-rp-hal.md | 16 +-
pico-pico/src/servo/how-servo-works.md | 6 +-
pico-pico/src/servo/servo-pico.md | 30 +--
.../std-to-no-std/cross-compilation/index.md | 4 +-
pico-pico/src/std-to-no-std/embassy-rp.md | 4 +-
pico-pico/src/std-to-no-std/no-std.md | 2 +-
pico-pico/src/std-to-no-std/panic-handler.md | 2 +-
pico-pico/src/thermistor/non-linear.md | 8 +-
pico-pico/src/thermistor/steinhart.md | 22 +--
pico-pico/src/ultrasonic/code.md | 8 +-
pico-pico/src/ultrasonic/hc-sr04-circuit.md | 30 +--
pico-pico/src/ultrasonic/using-rp-hal.md | 6 +-
rust-training/src/async-on-embedded.md | 4 +-
rust-training/src/async-rust-python.md | 6 +-
.../src/asynchronous-multitasking.md | 10 +-
rust-training/src/cargo-tooling.md | 2 +-
.../src/closures-and-dynamic-dispatch.md | 2 +-
rust-training/src/crate-engineering.md | 12 +-
rust-training/src/embassy-framework.md | 4 +-
rust-training/src/embedded-ecosystem.md | 6 +-
.../src/foreign-function-interface.md | 6 +-
rust-training/src/instructions.md | 6 +-
rust-training/src/introduction.md | 4 +-
rust-training/src/ownership-and-references.md | 2 +-
rust-training/src/portable-drivers.md | 2 +-
rust-training/src/rust-for-web-servers.md | 8 +-
rust-training/src/rust-in-the-browser.md | 12 +-
rust-training/src/rust-in-the-cloud.md | 4 +-
rust-training/src/testing-and-fuzzing.md | 4 +-
rust-training/src/traits-and-generics.md | 18 +-
std-training/book/src/01_intro.md | 4 +-
std-training/book/src/02_1_hardware.md | 2 +-
std-training/book/src/02_2_software.md | 10 +-
std-training/book/src/02_3_repository.md | 8 +-
std-training/book/src/02_4_hello_board.md | 4 +-
std-training/book/src/03_0_intro_workshop.md | 2 +-
std-training/book/src/03_1_project_orga.md | 4 +-
std-training/book/src/03_2_cargo_generate.md | 2 +-
std-training/book/src/03_3_2_http_client.md | 4 +-
std-training/book/src/03_4_http_server.md | 2 +-
std-training/book/src/03_5_1_mqtt.md | 2 +-
std-training/book/src/03_5_2_mqtt.md | 4 +-
std-training/book/src/03_5_3_mqtt.md | 2 +-
.../book/src/04_0_advanced_workshop.md | 2 +-
std-training/book/src/04_3_2_i2c.md | 4 +-
std-training/book/src/04_3_3_i2c.md | 2 +-
std-training/book/src/04_4_2_interrupts.md | 2 +-
std-training/book/src/04_4_3_interrupts.md | 2 +-
std-training/book/src/05_reference.md | 2 +-
207 files changed, 652 insertions(+), 650 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 51e6cff..a2802c4 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -54,14 +54,19 @@
| firmware | прошивка | |
| bootloader | загрузчик | |
| peripheral | периферия | |
+| pin (физический) | вывод | не «пин» и не «контакт»; тип `Pin` не переводим |
+| toolchain | тулчейн | |
+| borrow checker | анализатор заимствований | |
+| Cargo feature | feature-флаг | |
| register | регистр | |
| interrupt | прерывание | |
| polling | опрос | |
-| linker | линкер | |
-| duty cycle | коэффициент заполнения | для PWM |
+| linker | компоновщик | |
+| duty cycle | коэффициент заполнения | для ШИМ |
| buzzer | пищалка | |
| Future, Pin, Mutex, Send, Sync, PhantomData, newtype, typestate, UB | — | оставляем английскими |
-| GPIO, HAL, PAC, BSP, NVIC, SPI, I2C, UART, PWM, ADC, BLE, Wi-Fi | — | оставляем английскими |
+| ADC, DAC, PWM | АЦП, ЦАП, ШИМ | при первом упоминании добавляйте английскую расшифровку |
+| GPIO, HAL, PAC, BSP, NVIC, SPI, I2C, UART, BLE, Wi-Fi | — | оставляем английскими |
Если нужного термина нет в таблице, посмотрите, как он переведён в других книгах сборника, и используйте тот же вариант.
diff --git a/comprehensive-rust/po/ru.po b/comprehensive-rust/po/ru.po
index 03e28f0..393495b 100644
--- a/comprehensive-rust/po/ru.po
+++ b/comprehensive-rust/po/ru.po
@@ -1657,7 +1657,7 @@ msgstr "Сериализатор: полная реализация"
#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system.md
msgid "Borrow checking invariants"
-msgstr "Инварианты проверки заимствований"
+msgstr "Инварианты анализатора заимствований"
#: src/SUMMARY.md src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/generalizing-ownership.md
msgid "Lifetimes and Borrows: the Abstract Rules"
@@ -2161,7 +2161,7 @@ msgstr "Курс также доступен [в формате EPUB](comprehens
#: src/index.md
msgid "The goal of the course is to teach you Rust. We assume you don't know anything about Rust and hope to:"
-msgstr "Цель курса --- научить вас языку Rust. Мы предполагаем, что вы ничего не знаете о Rust и надеемся:"
+msgstr "Цель курса --- научить вас языку Rust. Мы предполагаем, что вы ничего не знаете о Rust, и надеемся:"
#: src/index.md
msgid "Give you a comprehensive understanding of the Rust syntax and language."
@@ -2189,7 +2189,7 @@ msgstr "[Android](android.md): рассчитанный на полдня кур
#: src/index.md
msgid "[Chromium](chromium.md): a half-day course on using Rust in Chromium-based browsers. This includes interoperability with C++ and how to include third-party crates in Chromium."
-msgstr "[Chromium](chromium.md): полудневный курс по использованию Rust в браузерах на базе Chromium. Включает взаимодействие с C++ и подключение сторонних крейтов в Chromium."
+msgstr "[Chromium](chromium.md): рассчитанный на полдня курс по использованию Rust в браузерах на базе Chromium. Включает взаимодействие с C++ и подключение сторонних крейтов в Chromium."
#: src/index.md
msgid "[Bare-metal](bare-metal.md): a whole-day class on using Rust for bare-metal (embedded) development. Both microcontrollers and application processors are covered."
@@ -2245,7 +2245,7 @@ msgstr "Перед проведением курса желательно:"
#: src/running-the-course.md
msgid "Make yourself familiar with the course material. We've included speaker notes to help highlight the key points (please help us by contributing more speaker notes!). When presenting, you should make sure to open the speaker notes in a popup (click the link with a little arrow next to \"Speaker Notes\"). This way you have a clean screen to present to the class."
-msgstr "Ознакомиться с материалами курса. Мы добавили заметки для преподавателя на некоторых страницах, чтобы выделить ключевые моменты (пожалуйста, помогайте нам, добавляя свои заметки для преподавателей!). Убедитесь в том, что открыли заметки для преподавателя во всплывающем окне (нажмите на ссылку с маленькой стрелкой рядом с ”Заметки для преподавателя”). У вас откроется отдельное окно с заметками для преподавателя, в то время как основное окно вы можете демонстрировать классу."
+msgstr "Ознакомиться с материалами курса. Мы добавили заметки для преподавателя на некоторых страницах, чтобы выделить ключевые моменты (пожалуйста, помогайте нам, добавляя свои заметки для преподавателей!). Убедитесь в том, что открыли заметки для преподавателя во всплывающем окне (нажмите на ссылку с маленькой стрелкой рядом с «Заметки для преподавателя»). У вас откроется отдельное окно с заметками для преподавателя, в то время как основное окно вы можете демонстрировать классу."
#: src/running-the-course.md
msgid "Decide on the dates. Since the course takes four days, we recommend that you schedule the days over two weeks. Course participants have said that they find it helpful to have a gap in the course since it helps them process all the information we give them."
@@ -2257,7 +2257,7 @@ msgstr "Найдите помещение, достаточно просторн
#: src/running-the-course.md
msgid "On the day of your course, show up to the room a little early to set things up. We recommend presenting directly using `mdbook serve` running on your laptop (see the [installation instructions](https://github.com/google/comprehensive-rust#building)). This ensures optimal performance with no lag as you change pages. Using your laptop will also allow you to fix typos as you or the course participants spot them."
-msgstr "В день занятия приходите в аудиторию немного раньше, чтобы всё подготовить. Мы рекомендуем показывать слайды используя `mdbook serve`, запущенного на вашем ноутбуке (см. [installation instructions](https://github.com/r007/EmbeddedRust-Rus/tree/main/comprehensive-rust#building)). Это обеспечивает оптимальную производительность без задержек при смене страниц. Использование ноутбука также позволит вам исправлять опечатки по мере их обнаружения вами или участниками курса."
+msgstr "В день занятия приходите в аудиторию немного раньше, чтобы всё подготовить. Мы рекомендуем показывать слайды с помощью `mdbook serve`, запущенного на вашем ноутбуке (см. [инструкцию по установке](https://github.com/r007/EmbeddedRust-Rus/tree/main/comprehensive-rust#building)). Это обеспечивает оптимальную производительность без задержек при смене страниц. Использование ноутбука также позволит вам исправлять опечатки по мере их обнаружения вами или участниками курса."
#: src/running-the-course.md
msgid "Let people solve the exercises by themselves or in small groups. We typically spend 30-45 minutes on exercises in the morning and in the afternoon (including time to review the solutions). Make sure to ask people if they're stuck or if there is anything you can help with. When you see that several people have the same problem, call it out to the class and offer a solution, e.g., by showing people where to find the relevant information in the standard library."
@@ -2413,7 +2413,7 @@ msgstr "Глубокое погружение"
#: src/running-the-course/course-structure.md
msgid "In addition to the 4-day class on Rust Fundamentals, we cover some more specialized topics:"
-msgstr "В дополнение к 4-х дневному курсу по основам Rust, мы рассмотрим ещё несколько специализированных тем:"
+msgstr "В дополнение к четырёхдневному курсу по основам Rust мы рассмотрим ещё несколько специализированных тем:"
#: src/running-the-course/course-structure.md
msgid "Rust in Android"
@@ -2425,7 +2425,7 @@ msgstr "Углублённый курс [Rust в Android](../android.md) зан
#: src/running-the-course/course-structure.md
msgid "You will need an [AOSP checkout](https://source.android.com/docs/setup/download/downloading). Make a checkout of the [course repository](https://github.com/google/comprehensive-rust) on the same machine and move the `src/android/` directory into the root of your AOSP checkout. This will ensure that the Android build system sees the `Android.bp` files in `src/android/`."
-msgstr "Вам потребуется [AOSP](https://source.android.com/docs/setup/download/downloading). Загрузите [репозиторий курса](https://github.com/r007/EmbeddedRust-Rus/tree/main/comprehensive-rust) на тот же компьютер, что и курс и переместите каталог `src/android/` в корневой каталог вашего AOSP. Это гарантирует, что система сборки Android увидит файлы `Android.bp` в `src/android/`."
+msgstr "Вам потребуется [AOSP](https://source.android.com/docs/setup/download/downloading). Загрузите [репозиторий курса](https://github.com/r007/EmbeddedRust-Rus/tree/main/comprehensive-rust) на тот же компьютер, что и AOSP, и переместите каталог `src/android/` в корневой каталог вашего AOSP. Это гарантирует, что система сборки Android увидит файлы `Android.bp` в `src/android/`."
#: src/running-the-course/course-structure.md
msgid "Ensure that `adb sync` works with your emulator or real device and pre-build all Android examples using `src/android/build_all.sh`. Read the script to see the commands it runs and make sure they work when you run them by hand."
@@ -2530,7 +2530,7 @@ msgstr "Формат"
#: src/running-the-course/course-structure.md
msgid "The course is meant to be very interactive and we recommend letting the questions drive the exploration of Rust!"
-msgstr "Курс задуман весьма интерактивным, и мы рекомендуем, чтобы вопросы содействовали изучению Rust!"
+msgstr "Курс задуман очень интерактивным, и мы рекомендуем позволять вопросам направлять изучение Rust!"
#: src/running-the-course/keyboard-shortcuts.md
msgid "There are several useful keyboard shortcuts in mdBook:"
@@ -2642,7 +2642,7 @@ msgstr "Полный список переводов с их текущим ст
#: src/running-the-course/translations.md
msgid "If you want to help with this effort, please see [our instructions](https://github.com/google/comprehensive-rust/blob/main/TRANSLATIONS.md) for how to get going. Translations are coordinated on the [issue tracker](https://github.com/google/comprehensive-rust/issues/282)."
-msgstr "Если вы хотите помочь в этом, пожалуйста, ознакомьтесь с [our instructions](https://github.com/r007/EmbeddedRust-Rus/blob/main/comprehensive-rust/TRANSLATIONS.md) о том, как приступить к работе. Переводы координируются с помощью [issue tracker](https://github.com/r007/EmbeddedRust-Rus/issues/282)."
+msgstr "Если вы хотите помочь в этом, пожалуйста, прочитайте [наши инструкции](https://github.com/r007/EmbeddedRust-Rus/blob/main/comprehensive-rust/TRANSLATIONS.md) о том, как приступить к работе. Переводы координируются в [трекере задач](https://github.com/r007/EmbeddedRust-Rus/issues/282)."
#: src/running-the-course/translations.md
msgid "This is a good opportunity to thank the volunteers who have contributed to the translations."
@@ -2698,11 +2698,11 @@ msgstr "`rustc`: компилятор Rust, который превращает
#: src/cargo/rust-ecosystem.md
msgid "`cargo`: the Rust dependency manager and build tool. Cargo knows how to download dependencies, usually hosted on , and it will pass them to `rustc` when building your project. Cargo also comes with a built-in test runner which is used to execute unit tests."
-msgstr "`cargo`: менеджер зависимостей и система сборки Rust. Cargo умеет загружать зависимости, обычно размещённые на , и передавать их `rustc` при сборке проекта. Cargo также включает встроенный запускатель тестов, который выполняет модульные тесты."
+msgstr "`cargo`: менеджер зависимостей и система сборки Rust. Cargo умеет загружать зависимости, обычно размещённые на , и передавать их `rustc` при сборке проекта. Cargo также включает встроенное средство запуска тестов, которое выполняет модульные тесты."
#: src/cargo/rust-ecosystem.md
msgid "`rustup`: the Rust toolchain installer and updater. This tool is used to install and update `rustc` and `cargo` when new versions of Rust are released. In addition, `rustup` can also download documentation for the standard library. You can have multiple versions of Rust installed at once and `rustup` will let you switch between them as needed."
-msgstr "`rustup`: установщик и обновитель инструментария Rust. Этот инструмент используется для установки и обновления `rustc` и `cargo` при выходе новых версий Rust. Кроме того, `rustup` может загружать документацию стандартной библиотеки. Можно одновременно установить несколько версий Rust, и `rustup` позволит переключаться между ними по мере необходимости."
+msgstr "`rustup`: установщик и средство обновления инструментария Rust. Этот инструмент используется для установки и обновления `rustc` и `cargo` при выходе новых версий Rust. Кроме того, `rustup` может загружать документацию стандартной библиотеки. Можно одновременно установить несколько версий Rust, и `rustup` позволит переключаться между ними по мере необходимости."
#: src/cargo/rust-ecosystem.md src/types-and-values/hello-world.md src/references/exclusive.md src/memory-management/move.md src/error-handling/try.md src/unsafe-rust/unsafe-functions/calling.md src/android/setup.md src/concurrency/async/async-await.md
msgid "Key points:"
@@ -2710,15 +2710,15 @@ msgstr "Ключевые моменты:"
#: src/cargo/rust-ecosystem.md
msgid "Rust has a rapid release schedule with a new release coming out every six weeks. New releases maintain backwards compatibility with old releases --- plus they enable new functionality."
-msgstr "У Rust стремительный график релизов: новая версия выходит каждые шесть недель. Новые версии поддерживают обратную совместимость со старыми версиями --- в дополнение они предоставляют новые функциональные возможности."
+msgstr "У Rust стремительный график релизов: новая версия выходит каждые шесть недель. Новые версии обратно совместимы со старыми и при этом добавляют новые возможности."
#: src/cargo/rust-ecosystem.md
msgid "There are three release channels: \"stable\", \"beta\", and \"nightly\"."
-msgstr "Существует три вида релизов: ”stable”, ”beta” и ”nightly”."
+msgstr "Существует три вида релизов: «stable», «beta» и «nightly»."
#: src/cargo/rust-ecosystem.md
msgid "New features are being tested on \"nightly\", \"beta\" is what becomes \"stable\" every six weeks."
-msgstr "Новые функции тестируются на ”nightly”, ”beta” --- это то, что становится ”stable” каждые шесть недель."
+msgstr "Новые возможности тестируются в «nightly», а «beta» --- это то, что становится «stable» каждые шесть недель."
#: src/cargo/rust-ecosystem.md
msgid "Dependencies can also be resolved from alternative [registries](https://doc.rust-lang.org/cargo/reference/registries.html), git, folders, and more."
@@ -2730,7 +2730,7 @@ msgstr "У Rust также есть [редакции](https://doc.rust-lang.org
#: src/cargo/rust-ecosystem.md
msgid "The editions are allowed to make backwards incompatible changes to the language."
-msgstr "Редакциями позволено вносить обратно--несовместимые изменения в язык."
+msgstr "Редакциями позволено вносить обратно несовместимые изменения в язык."
#: src/cargo/rust-ecosystem.md
msgid "To prevent breaking code, editions are opt-in: you select the edition for your crate via the `Cargo.toml` file."
@@ -2754,7 +2754,7 @@ msgstr "Структура проекта/пакета"
#: src/cargo/rust-ecosystem.md
msgid "[workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)"
-msgstr "[workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)"
+msgstr "[рабочие пространства (workspaces)](https://doc.rust-lang.org/cargo/reference/workspaces.html)"
#: src/cargo/rust-ecosystem.md
msgid "Dev Dependencies and Runtime Dependency management/caching"
@@ -2762,11 +2762,11 @@ msgstr "Управление зависимостями для разработ
#: src/cargo/rust-ecosystem.md
msgid "[build scripting](https://doc.rust-lang.org/cargo/reference/build-scripts.html)"
-msgstr "[build scripting](https://doc.rust-lang.org/cargo/reference/build-scripts.html)"
+msgstr "[скрипты сборки (build scripts)](https://doc.rust-lang.org/cargo/reference/build-scripts.html)"
#: src/cargo/rust-ecosystem.md
msgid "[global installation](https://doc.rust-lang.org/cargo/commands/cargo-install.html)"
-msgstr "[global installation](https://doc.rust-lang.org/cargo/commands/cargo-install.html)"
+msgstr "[глобальная установка (`cargo install`)](https://doc.rust-lang.org/cargo/commands/cargo-install.html)"
#: src/cargo/rust-ecosystem.md
msgid "It is also extensible with sub command plugins as well (such as [cargo clippy](https://github.com/rust-lang/rust-clippy))."
@@ -2774,7 +2774,7 @@ msgstr "Он также расширяем с помощью плагинов п
#: src/cargo/rust-ecosystem.md
msgid "Read more from the [official Cargo Book](https://doc.rust-lang.org/cargo/)"
-msgstr "Подробнее читайте в [official Cargo Book](https://doc.rust-lang.org/cargo/)"
+msgstr "Подробнее читайте в [официальной книге по Cargo](https://doc.rust-lang.org/cargo/)"
#: src/cargo/code-samples.md
msgid "Code Samples in This Training"
@@ -2826,7 +2826,7 @@ msgstr "Запуск кода локально с помощью Cargo"
#: src/cargo/running-locally.md
msgid "If you want to experiment with the code on your own system, then you will need to first install Rust. Do this by following the [instructions in the Rust Book](https://doc.rust-lang.org/book/ch01-01-installation.html). This should give you a working `rustc` and `cargo`. At the time of writing, the latest stable Rust release has these version numbers:"
-msgstr "Если вы хотите поэкспериментировать с кодом на своей системе, то вам нужно будет сначала установить Rust. Сделайте это, следуя [инструкциям в The Rust Book](https://doc.rust-lang.org/book/ch01-01-installation.html). В вашей системе появятся инструменты `rustc` и `cargo`. На момент написания статьи последний стабильный выпуск Rust имеет следующие версии:"
+msgstr "Если вы хотите поэкспериментировать с кодом на своей системе, то вам нужно будет сначала установить Rust. Сделайте это, следуя [инструкциям в The Rust Book](https://doc.rust-lang.org/book/ch01-01-installation.html). В вашей системе появятся инструменты `rustc` и `cargo`. На момент написания курса последний стабильный выпуск Rust имеет следующие версии:"
#: src/cargo/running-locally.md
msgid "You can use any later version too since Rust maintains backwards compatibility."
@@ -2838,15 +2838,15 @@ msgstr "После этого выполните следующие шаги, ч
#: src/cargo/running-locally.md
msgid "Click the \"Copy to clipboard\" button on the example you want to copy."
-msgstr "Нажмите кнопку ”Copy to clipboard” на примере кода, который вы хотите скопировать."
+msgstr "Нажмите кнопку «Copy to clipboard» на примере кода, который вы хотите скопировать."
#: src/cargo/running-locally.md
msgid "Use `cargo new exercise` to create a new `exercise/` directory for your code:"
-msgstr "Используйте `cargo new exercise`, чтобы создать новую директорию `exercise/` для вашего кода:"
+msgstr "Используйте `cargo new exercise`, чтобы создать новый каталог `exercise/` для вашего кода:"
#: src/cargo/running-locally.md
msgid "Navigate into `exercise/` and use `cargo run` to build and run your binary:"
-msgstr "Перейдите в директорию `exercise/` и выполните `cargo run` для сборки и запуска исполняемого файла:"
+msgstr "Перейдите в каталог `exercise/` и выполните `cargo run` для сборки и запуска исполняемого файла:"
#: src/cargo/running-locally.md
msgid "Replace the boilerplate code in `src/main.rs` with your own code. For example, using the example on the previous page, make `src/main.rs` look like"
@@ -2858,7 +2858,7 @@ msgstr "Используйте `cargo run` для сборки и запуска
#: src/cargo/running-locally.md
msgid "Use `cargo check` to quickly check your project for errors, use `cargo build` to compile it without running it. You will find the output in `target/debug/` for a normal debug build. Use `cargo build --release` to produce an optimized release build in `target/release/`."
-msgstr "Используйте `cargo check` для быстрой проверки проекта на наличие ошибок и `cargo build` для компиляции проекта без его запуска. Вы найдете результат в директории `target/debug/` для отладочной сборки. Используйте `cargo build --release` для создания оптимизированной финальной сборки в `target/release/`."
+msgstr "Используйте `cargo check` для быстрой проверки проекта на наличие ошибок и `cargo build` для компиляции проекта без его запуска. Вы найдёте результат в каталоге `target/debug/` для отладочной сборки. Используйте `cargo build --release` для создания оптимизированной финальной сборки в `target/release/`."
#: src/cargo/running-locally.md
msgid "You can add dependencies for your project by editing `Cargo.toml`. When you run `cargo` commands, it will automatically download and compile missing dependencies for you."
@@ -2922,7 +2922,7 @@ msgstr "Часто вопросы будут приводить к обсужд
#: src/welcome-day-1.md
msgid "This is perfectly okay! Repetition is an important part of learning. Remember that the slides are just a support and you are free to skip them as you like."
-msgstr "Это совершенно нормально! Повторение --- важная часть обучения. Помните, что слайды --- это всего лишь вспомогательный материал, и вы вольны пропускать их по своему усмотрению."
+msgstr "Это совершенно нормально! Повторение --- важная часть обучения. Помните, что слайды --- это всего лишь вспомогательный материал, и вы вольны пропускать их по своему усмотрению."
#: src/welcome-day-1.md
msgid "The idea for the first day is to show the \"basic\" things in Rust that should have immediate parallels in other languages. The more advanced parts of Rust come on the subsequent days."
@@ -3114,7 +3114,7 @@ msgstr "Обязательно спросите учащихся, с каким
#: src/hello-world/benefits.md
msgid "Experience with C or C++: Rust eliminates a whole class of _runtime errors_ via the borrow checker. You get performance like in C and C++, but you don't have the memory unsafety issues. In addition, you get a modern language with constructs like pattern matching and built-in dependency management."
-msgstr "Опыт работы с C или C++: Rust устраняет целый класс _ошибок времени выполнения_ с помощью анализатора заимствований. Вы получаете производительность, как в C и C++, минуя проблем с безопасностью памяти. Кроме того, вы получаете современный язык с такими конструкциями, как сопоставление с образцом и встроенное управление зависимостями."
+msgstr "Опыт работы с C или C++: Rust устраняет целый класс _ошибок времени выполнения_ с помощью анализатора заимствований. Вы получаете производительность, как в C и C++, не сталкиваясь с проблемами безопасности памяти. Кроме того, вы получаете современный язык с такими конструкциями, как сопоставление с образцом и встроенное управление зависимостями."
#: src/hello-world/benefits.md
msgid "Experience with Java, Go, Python, JavaScript...: You get the same memory safety as in those languages, plus a similar high-level language feeling. In addition you get fast and predictable performance like C and C++ (no garbage collector) as well as access to low-level hardware (should you need it)."
@@ -3146,7 +3146,7 @@ msgstr "Этот сегмент займёт около 40 минут. Он вк
#: src/types-and-values/hello-world.md
msgid "Let us jump into the simplest possible Rust program, a classic Hello World program:"
-msgstr "Давайте перейдём к самой простой из возможных программ на Rust, классической программе Привет, мир!"
+msgstr "Давайте перейдём к самой простой из возможных программ на Rust, классической программе «Привет, мир!»"
#: src/types-and-values/hello-world.md src/control-flow-basics/if.md src/control-flow-basics/match.md src/control-flow-basics/loops/for.md src/control-flow-basics/loops/loop.md src/control-flow-basics/break-continue/labels.md src/tuples-and-arrays/arrays.md src/references/strings.md src/references/dangling.md src/user-defined-types/static.md src/pattern-matching/match.md src/methods-and-traits/traits/implementing.md src/methods-and-traits/traits/supertraits.md src/methods-and-traits/traits/associated-types.md src/generics/generic-traits.md src/generics/dyn-trait.md src/smart-pointers/trait-objects.md src/borrowing/examples.md src/lifetimes/lifetime-elision.md src/lifetimes/struct-lifetimes.md src/lifetimes/exercise.md src/lifetimes/solution.md src/iterators/for.md src/iterators/motivation.md src/iterators/helpers.md src/iterators/collect.md src/modules/encapsulation.md src/error-handling/thiserror.md src/error-handling/anyhow.md src/android/aidl/example-service/service-bindings.md src/android/aidl/example-service/service.md src/android/aidl/example-service/server.md src/android/aidl/example-service/client.md src/android/aidl/example-service/changing-definition.md src/android/aidl/example-service/changing-implementation.md src/android/aidl/types/objects.md src/android/aidl/types/parcelables.md src/android/aidl/types/file-descriptor.md src/android/testing.md src/android/testing/googletest.md src/android/testing/mocking.md src/concurrency/threads/plain.md src/concurrency/threads/scoped.md src/concurrency/channels/senders-receivers.md src/concurrency/shared-state/arc.md src/concurrency/shared-state/mutex.md src/concurrency/shared-state/example.md src/concurrency/sync-exercises/dining-philosophers.md src/concurrency/sync-exercises/link-checker.md src/concurrency/sync-exercises/solutions.md src/concurrency/async/async-await.md src/concurrency/async/futures.md src/concurrency/async/runtimes/tokio.md src/concurrency/async/tasks.md src/concurrency/async-control-flow/channels.md src/concurrency/async-control-flow/join.md src/concurrency/async-control-flow/select.md src/concurrency/async-pitfalls/blocking-executor.md src/concurrency/async-pitfalls/pin.md src/concurrency/async-pitfalls/async-traits.md src/concurrency/async-pitfalls/cancellation.md src/concurrency/async-exercises/dining-philosophers.md src/concurrency/async-exercises/chat-app.md src/concurrency/async-exercises/solutions.md
msgid "// Copyright 2024 Google LLC\n"
@@ -3385,7 +3385,7 @@ msgstr "Здесь очень важно отметить, что это отн
# Number i18n seems inapplicable here.
#: src/types-and-values/inference.md
msgid "When nothing constrains the type of an integer literal, Rust defaults to `i32`. This sometimes appears as `{integer}` in error messages. Similarly, floating-point literals default to `f64`."
-msgstr "По умолчанию, в отсутствие ограничений, тип целочисленого литерала будет выведен как `i32`. Что в сообщениях об ошибках иногда показывается как `{integer}`. Аналогично, умолчание для литералов чисел с плавающей точкой --- `f64`"
+msgstr "По умолчанию, в отсутствие ограничений, тип целочисленного литерала будет выведен как `i32`. В сообщениях об ошибках он иногда отображается как `{integer}`. Аналогично, умолчание для литералов чисел с плавающей точкой --- `f64`"
# Localization of Rust error messages doesn't seem to be complete.
# https://github.com/rust-lang/rfcs/issues/1843
@@ -3574,7 +3574,7 @@ msgstr "\"huge\""
#: src/control-flow-basics/if.md
msgid "In addition, you can use `if` as an expression. The last expression of each block becomes the value of the `if` expression:"
-msgstr "Помимо этого, можно использовать `if` как выражение. Последнее выражение внутри одного из блоков (в зависимости от значения условия) становится значением всего выражения `if`:"
+msgstr "Помимо этого, можно использовать `if` как выражение. Последнее выражение внутри одного из блоков (в зависимости от значения условия) становится значением всего выражения `if`:"
#: src/control-flow-basics/if.md
msgid "\"small\""
@@ -3714,7 +3714,7 @@ msgstr "\"This line gets skipped\""
#: src/control-flow-basics/functions.md
msgid "Declaration parameters are followed by a type (the reverse of some programming languages), then a return type."
-msgstr "В объявлении функции за каждым параметром следует его тип (противоположно некоторым языкам программирования), затем тип возвращаемого значения."
+msgstr "В объявлении функции за каждым параметром следует его тип (в отличие от некоторых языков программирования), затем тип возвращаемого значения."
#: src/control-flow-basics/functions.md
msgid "The last expression in a function body (or any block) becomes the return value. Simply omit the `;` at the end of the expression. The `return` keyword can be used for early return, but the \"bare value\" form is idiomatic at the end of a function (refactor `gcd` to use a `return`)."
@@ -3902,7 +3902,7 @@ msgstr "Массивы также можно инициализировать к
#: src/tuples-and-arrays/arrays.md
msgid "A value of the array type `[T; N]` holds `N` (a compile-time constant) elements of the same type `T`. Note that the length of the array is _part of its type_, which means that `[u8; 3]` and `[u8; 4]` are considered two different types. Slices, which have a size determined at runtime, are covered later."
-msgstr "Значение массива `[T; N]` содержит `N` элементов одинакового типа `T`. Где `N` (длина массива) --- это константа времени компиляции. Следует обратить внимание, что длина является _частью типа_, как следствие `[u8; 3]` и `[u8; 4]` --- это разные типы. Срезы, длина которых определяется во время выполнения, рассматриваются в курсе позднее."
+msgstr "Значение массива `[T; N]` содержит `N` элементов одинакового типа `T`. Где `N` (длина массива) --- это константа времени компиляции. Обратите внимание: длина является _частью типа_, поэтому `[u8; 3]` и `[u8; 4]` --- это разные типы. Срезы, длина которых определяется во время выполнения, рассматриваются в курсе позднее."
#: src/tuples-and-arrays/arrays.md
msgid "Try accessing an out-of-bounds array element. The compiler is able to determine that the index is unsafe, and will not compile the code:"
@@ -3937,11 +3937,11 @@ msgstr "Отладочный вывод"
# Should not that much confuse attendees, since it's in the speaker notes.
#: src/tuples-and-arrays/arrays.md
msgid "The `println!` macro asks for the debug implementation with the `?` format parameter: `{}` gives the default output, `{:?}` gives the debug output. Types such as integers and strings implement the default output, but arrays only implement the debug output. This means that we must use debug output here."
-msgstr "Параметр форматирования `?` предписывает макросу `println!` запросить реализацию трейта отладочного вывода: `{}` запрашивает форматирование по умолчанию (`std::fmt::Display`), `{:?}` -- отладочное представление (`std::fmt::Debug`). Другие, например, целочисленные типы и строки реализуют трейт `Display`, но для массовов реализован только трейт `Debug`. Поэтому использование `{:?}` здесь обязательно."
+msgstr "Параметр форматирования `?` предписывает макросу `println!` запросить реализацию трейта отладочного вывода: `{}` запрашивает форматирование по умолчанию (`std::fmt::Display`), `{:?}` -- отладочное представление (`std::fmt::Debug`). Например, целочисленные типы и строки реализуют трейт `Display`, но для массивов реализован только трейт `Debug`. Поэтому использование `{:?}` здесь обязательно."
#: src/tuples-and-arrays/arrays.md
msgid "Adding `#`, eg `{a:#?}`, invokes a \"pretty printing\" format, which can be easier to read."
-msgstr "Добавление `#`, например `{a:#?}`, позволяет использовать более наглядный формат \"красивой печати\", с отступами и переносами строк."
+msgstr "Добавление `#`, например `{a:#?}`, позволяет использовать более наглядный формат «красивой печати» с отступами и переносами строк."
#: src/tuples-and-arrays/tuples.md
msgid "Like arrays, tuples have a fixed length."
@@ -3953,11 +3953,11 @@ msgstr "Кортежи группируют значения разных тип
#: src/tuples-and-arrays/tuples.md
msgid "Fields of a tuple can be accessed by the period and the index of the value, e.g. `t.0`, `t.1`."
-msgstr "Доступ к полям кортежа можно получить используя точку и индекс значения, например `t.0`, `t.1`."
+msgstr "Доступ к полям кортежа можно получить с помощью точки и индекса значения, например `t.0`, `t.1`."
#: src/tuples-and-arrays/tuples.md
msgid "The empty tuple `()` is referred to as the \"unit type\" and signifies absence of a return value, akin to `void` in other languages."
-msgstr "Пустой кортеж `()` называется _единичным типом_ и обозначает пустое значение или пустой возвращаемый тип. Сходно с использованием `void` в других языках."
+msgstr "Пустой кортеж `()` называется _единичным типом_ и обозначает пустое значение или пустой возвращаемый тип. Похоже на `void` в других языках."
#: src/tuples-and-arrays/tuples.md
msgid "Unlike arrays, tuples cannot be used in a `for` loop. This is because a `for` loop requires all the elements to have the same type, which may not be the case for a tuple."
@@ -3998,7 +3998,7 @@ msgstr "\"unordered\""
#: src/tuples-and-arrays/destructuring.md
msgid "The patterns used here are \"irrefutable\", meaning that the compiler can statically verify that the value on the right of `=` has the same structure as the pattern."
-msgstr "Используемые здесь шаблоны являются \"неопровержимыми\", что означает, что компилятор может статически проверить, что значение справа от `=` имеет ту же структуру, что и шаблон."
+msgstr "Используемые здесь шаблоны являются «неопровержимыми», то есть компилятор может статически проверить, что значение справа от `=` имеет ту же структуру, что и шаблон."
#: src/tuples-and-arrays/destructuring.md
msgid "A variable name is an irrefutable pattern that always matches any value, hence why we can also use `let` to declare a single variable."
@@ -4118,7 +4118,7 @@ msgstr "В некоторых случаях Rust автоматически р
#: src/references/shared.md
msgid "In this example, `r` is mutable so that it can be reassigned (`r = &b`). Note that this re-binds `r`, so that it refers to something else. This is different from C++, where assignment to a reference changes the referenced value."
-msgstr "В этом примере `r` объявлена изменяемой, чтобы её можно было переназначить (`r = &b`). Обратите внимание, что это перепривязывает `r`, так что она теперь ссылается на другое значение. Это отличается от C++, где присваивание ссылке меняет значение, на которое она указывает."
+msgstr "В этом примере `r` объявлена изменяемой, чтобы её можно было переназначить (`r = &b`). Обратите внимание, что это меняет привязку `r`: она теперь ссылается на другое значение. Это отличается от C++, где присваивание ссылке меняет значение, на которое она указывает."
#: src/references/shared.md
msgid "A shared reference does not allow modifying the value it refers to, even if that value was mutable. Try `*r = 'X'`."
@@ -4158,7 +4158,7 @@ msgstr "Мы создаем срез, заимствуя `a` и указывая
#: src/references/slices.md
msgid "If the slice starts at index 0, Rust’s range syntax allows us to drop the starting index, meaning that `&a[0..a.len()]` and `&a[..a.len()]` are identical."
-msgstr "Если срез начинается с индекса 0, синтаксис Rust позволяет отбросить начальный индекс, таким образом, `&a[0..a.len()]` и `&a[..a.len()]` идентичны ."
+msgstr "Если срез начинается с индекса 0, синтаксис Rust позволяет отбросить начальный индекс, таким образом, `&a[0..a.len()]` и `&a[..a.len()]` идентичны."
#: src/references/slices.md
msgid "The same is true for the last index, so `&a[2..a.len()]` and `&a[2..]` are identical."
@@ -4186,7 +4186,7 @@ msgstr "Нельзя добавлять элементы в срез, так к
#: src/references/slices.md
msgid "You can't grow a slice to point to a larger section of the backing buffer. A slice does not have information about the length of the underlying buffer and so you can't know how large the slice can be grown."
-msgstr "Нельзя расширить срез так, чтобы он указывал на бо́льшую часть нижележащего буфера. Срез не знает длины нижележащего буфера, поэтому нельзя понять, насколько его можно расширить."
+msgstr "Нельзя расширить срез так, чтобы он указывал на больший участок нижележащего буфера. Срез не знает длины нижележащего буфера, поэтому нельзя понять, насколько его можно расширить."
#: src/references/slices.md
msgid "To get a larger slice you have to go back to the original buffer and create a larger slice from there."
@@ -4202,7 +4202,7 @@ msgstr "`&str` --- это срез из байтов в кодировке UTF-8
#: src/references/strings.md
msgid "`String` is an owned buffer of UTF-8 encoded bytes, similar to `Vec`."
-msgstr "`String` --- это принадлежащий владельцу буфер из байтов в кодировке UTF-8, похожий на `Vec`."
+msgstr "`String` --- это владеющий буфер из байтов в кодировке UTF-8, похожий на `Vec`."
#: src/references/strings.md src/std-traits/read-and-write.md
msgid "\"World\""
@@ -4230,7 +4230,7 @@ msgstr "`&str` задаёт строковый срез --- неизменяем
#: src/references/strings.md
msgid "Rust's `String` type is a wrapper around a vector of bytes. As with a `Vec`, it is owned."
-msgstr "Тип `String` в Rust --- это обёртка над вектором байтов. Как и `Vec`, он принадлежит владельцу."
+msgstr "Тип `String` в Rust --- это обёртка над вектором байтов. Как и `Vec`, он владеет своими данными."
#: src/references/strings.md
msgid "As with many other types `String::from()` creates a string from a string literal; `String::new()` creates a new empty string, to which string data can be added using the `push()` and `push_str()` methods."
@@ -4238,7 +4238,7 @@ msgstr "Как и многие другие типы, `String::from()` созд
#: src/references/strings.md
msgid "The `format!()` macro is a convenient way to generate an owned string from dynamic values. It accepts the same format specification as `println!()`."
-msgstr "Макрос `format!()` --- удобный способ создать принадлежащую владельцу строку из динамических значений. Он принимает ту же спецификацию формата, что и `println!()`."
+msgstr "Макрос `format!()` --- удобный способ создать владеющую строку из динамических значений. Он принимает ту же спецификацию формата, что и `println!()`."
#: src/references/strings.md
msgid "You can borrow `&str` slices from `String` via `&` and optionally range selection. If you select a byte range that is not aligned to character boundaries, the expression will panic. The `chars` iterator iterates over characters and is preferred over trying to get character boundaries right."
@@ -4996,7 +4996,7 @@ msgstr "Тот же эффект возникает с `match &mut m`: захв
#: src/pattern-matching/destructuring-structs.md
msgid "The distinction between a capture and a constant expression can be hard to spot. Try changing the `0` in the first arm to a variable, and see that it subtly doesn't work. Change it to a `const` and see it working again."
-msgstr "Различие между захватом и константным выражением может быть трудно заметить. Попробуйте заменить `0` в первой ветке на переменную и посмотрите, что тонко перестаёт работать. Замените на `const`, и всё снова заработает."
+msgstr "Различие между захватом и константным выражением может быть трудно заметить. Попробуйте заменить `0` в первой ветке на переменную и посмотрите, что при этом незаметно перестаёт работать. Замените на `const`, и всё снова заработает."
#: src/pattern-matching/destructuring-enums.md
msgid "Like tuples, enums can also be destructured by matching:"
@@ -5060,7 +5060,7 @@ msgstr "Выражение `let else`"
#: src/pattern-matching/let-control-flow/if-let.md
msgid "The [`if let` expression](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions) lets you execute different code depending on whether a value matches a pattern:"
-msgstr "[Выражение `if let`](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions) позволяет выполнять разные ветки кода в зависимости от того, соответствует ли какое-либо значение шаблону или нет:"
+msgstr "[Выражение `if let`](https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions) позволяет выполнять разные ветки кода в зависимости от того, соответствует ли какое-либо значение шаблону или нет:"
#: src/pattern-matching/let-control-flow/if-let.md
msgid "\"slept for {duration:?}\""
@@ -5068,7 +5068,7 @@ msgstr "\"slept for {duration:?}\""
#: src/pattern-matching/let-control-flow/if-let.md
msgid "Unlike `match`, `if let` does not have to cover all branches. This can make it more concise than `match`."
-msgstr "`if let` может быть более лаконично, чем `match`. Например, когда нужно проверить только один вариант. Выражение `match`, напротив, требует проверки всех вариантов."
+msgstr "`if let` может быть лаконичнее, чем `match`. Например, когда нужно проверить только один вариант. Выражение `match`, напротив, требует проверки всех вариантов."
#: src/pattern-matching/let-control-flow/if-let.md
msgid "A common usage is handling `Some` values when working with `Option`."
@@ -5100,7 +5100,7 @@ msgstr "Здесь [`String::pop`](https://doc.rust-lang.org/stable/std/string/s
#: src/pattern-matching/let-control-flow/while-let.md
msgid "Point out that the `while let` loop will keep going as long as the value matches the pattern."
-msgstr "Уточнить, что циклы `while let` будут продолжаться до тех пор, пока значение будет соответствовать шаблону."
+msgstr "Уточните, что циклы `while let` продолжаются, пока значение соответствует шаблону."
#: src/pattern-matching/let-control-flow/while-let.md
msgid "You could rewrite the `while let` loop as an infinite loop with an if statement that breaks when there is no value to unwrap for `name.pop()`. The `while let` provides syntactic sugar for the above scenario."
@@ -5416,7 +5416,7 @@ msgstr "Не все `.clone()` в примере выше здесь необх
#: src/methods-and-traits/exercise.md
msgid "Let's design a simple logging utility, using a trait `Logger` with a `log` method. Code that might log its progress can then take an `&impl Logger`. In testing, this might put messages in the test logfile, while in a production build it would send messages to a log server."
-msgstr "Давайте спроектируем простую утилиту логирования с трейтом `Logger`, у которого есть метод `log`. Код, который может записывать ход своей работы, затем может принимать `&impl Logger`. В тестах это может записывать сообщения в файл журнала тестов, а в производственной сборке --- отправлять сообщения на сервер логов."
+msgstr "Давайте спроектируем простую утилиту логирования с трейтом `Logger`, у которого есть метод `log`. Код, который может записывать ход своей работы, затем может принимать `&impl Logger`. В тестах это может записывать сообщения в файл журнала тестов, а в рабочей (production) сборке --- отправлять сообщения на сервер логов."
#: src/methods-and-traits/exercise.md
msgid "However, the `StderrLogger` given below logs all messages, regardless of verbosity. Your task is to write a `VerbosityFilter` type that will ignore messages above a maximum verbosity."
@@ -5496,7 +5496,7 @@ msgstr "В этом примере для `T` мы используем толь
#: src/generics/generic-functions.md
msgid "This is similar to C++ templates, but Rust partially compiles the generic function immediately, so that function must be valid for all types matching the constraints. For example, try modifying `pick` to return `left + right` if `cond` is false. Even if only the `pick` instantiation with integers is used, Rust still considers it invalid. C++ would let you do this."
-msgstr "Это похоже на шаблоны C++, но Rust частично компилирует обобщённую функцию сразу, поэтому функция должна быть корректна для всех типов, удовлетворяющих ограничениям. Например, попробуйте изменить `pick`, чтобы он возвращал `left + right`, если `cond` ложно. Даже если используется только инстанциация `pick` для целых, Rust всё равно считает код некорректным. C++ позволил бы сделать это."
+msgstr "Это похоже на шаблоны C++, но Rust частично компилирует обобщённую функцию сразу, поэтому функция должна быть корректна для всех типов, удовлетворяющих ограничениям. Например, попробуйте изменить `pick`, чтобы он возвращал `left + right`, если `cond` ложно. Даже если используется только версия `pick` для целых чисел, Rust всё равно считает код некорректным. C++ позволил бы сделать это."
#: src/generics/generic-functions.md
msgid "Generic code is turned into non-generic code based on the call sites. This is a zero-cost abstraction: you get exactly the same result as if you had hand-coded the data structures without the abstraction."
@@ -6002,7 +6002,7 @@ msgstr ""
#: src/std-types/docs.md
msgid "The contents are treated as Markdown. All published Rust library crates are automatically documented at [`docs.rs`](https://docs.rs) using the [rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html) tool. It is idiomatic to document all public items in an API using this pattern."
-msgstr "Содержимое интерпретируется как Markdown. Все опубликованные крейты библиотек Rust автоматически документируются на [`docs.rs`](https://docs.rs) с помощью инструмента [rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html). Документирование всех общедоступных элементов API используя этот подход является идиоматичным."
+msgstr "Содержимое интерпретируется как Markdown. Все опубликованные крейты библиотек Rust автоматически документируются на [`docs.rs`](https://docs.rs) с помощью инструмента [rustdoc](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html). Документировать таким образом все общедоступные элементы API --- идиоматичный подход."
#: src/std-types/docs.md
msgid "To document an item from inside the item (such as inside a module), use `//!` or `/*! .. */`, called \"inner doc comments\":"
@@ -6050,7 +6050,7 @@ msgstr "Можно вызвать панику при `None`, но нельзя
#: src/std-types/option.md
msgid "It's common to `unwrap`/`expect` all over the place when hacking something together, but production code typically handles `None` in a nicer fashion."
-msgstr "Когда что-то собирают на скорую руку, часто используют `unwrap`/`expect` повсюду, но производственный код обычно обрабатывает `None` более аккуратно."
+msgstr "Когда что-то собирают на скорую руку, часто используют `unwrap`/`expect` повсюду, но рабочий код обычно обрабатывает `None` более аккуратно."
#: src/std-types/option.md
msgid "Many of methods on `Option` such as `insert` and `take` can be viewed as treating it like a container with room for at most one element. Methods with similar names and behaviors exist on other container types."
@@ -6570,7 +6570,7 @@ msgstr "Синтаксис `..` называется [синтаксисом о
#: src/std-traits/exercise.md
msgid "In this example, you will implement the classic [\"ROT13\" cipher](https://en.wikipedia.org/wiki/ROT13). Copy this code to the playground, and implement the missing bits. Only rotate ASCII alphabetic characters, to ensure the result is still valid UTF-8."
-msgstr "В этом примере вы реализуете классический [шифр «ROT13»](https://en.wikipedia.org/wiki/ROT13). Скопируйте код в playground и реализуйте недостающие части. Поворачивайте только буквы ASCII, чтобы результат оставался корректным UTF-8."
+msgstr "В этом упражнении вы реализуете классический [шифр «ROT13»](https://en.wikipedia.org/wiki/ROT13). Скопируйте код в playground и реализуйте недостающие части. Поворачивайте только буквы ASCII, чтобы результат оставался корректным UTF-8."
#: src/std-traits/exercise.md
msgid "// Implement the `Read` trait for `RotDecoder`.\n"
@@ -6682,7 +6682,7 @@ msgstr "Если студенты спросят, можно упомянуть,
#: src/memory-management/review.md
msgid "We can inspect the memory layout with `unsafe` Rust. However, you should point out that this is rightfully unsafe!"
-msgstr "Можно исследовать раскладку памяти с помощью `unsafe` Rust. Однако стоит подчеркнуть, что это справедливо небезопасно!"
+msgstr "Можно исследовать раскладку памяти с помощью `unsafe` Rust. Однако стоит подчеркнуть, что это действительно небезопасно!"
#: src/memory-management/review.md src/testing/unit-tests.md
msgid "' '"
@@ -6756,7 +6756,7 @@ msgstr "Этот слайд призван помочь студентам, пр
#: src/memory-management/approaches.md
msgid "C must manage heap manually with `malloc` and `free`. Common errors include forgetting to call `free`, calling it multiple times for the same pointer, or dereferencing a pointer after the memory it points to has been freed."
-msgstr "C должен управлять кучей вручную с помощью `malloc` и `free`. Распространённые ошибки включают забывание вызвать `free`, вызов его несколько раз для одного указателя или разыменование указателя после того, как память, на которую он указывает, уже освобождена."
+msgstr "В C кучей нужно управлять вручную с помощью `malloc` и `free`. Распространённые ошибки включают забывание вызвать `free`, вызов его несколько раз для одного указателя или разыменование указателя после того, как память, на которую он указывает, уже освобождена."
#: src/memory-management/approaches.md
msgid "C++ has tools like smart pointers (`unique_ptr`, `shared_ptr`) that take advantage of language guarantees about calling destructors to ensure memory is freed when a function returns. It is still quite easy to misuse these tools and create similar bugs to C."
@@ -7552,7 +7552,7 @@ msgstr "Можно иметь ровно одну эксклюзивную сс
#: src/borrowing/borrowck.md
msgid "The \"outlives\" rule was demonstrated previously when we first looked at references. We review it here to show students that the borrow checking is following a few different rules to validate borrowing."
-msgstr "Правило «пережить» мы уже демонстрировали, когда впервые рассматривали ссылки. Здесь мы повторяем его, чтобы показать студентам, что проверка заимствований следует нескольким разным правилам."
+msgstr "Правило «пережить» мы уже демонстрировали, когда впервые рассматривали ссылки. Здесь мы повторяем его, чтобы показать студентам, что анализатор заимствований следует нескольким разным правилам."
#: src/borrowing/borrowck.md
msgid "The above code does not compile because `a` is borrowed as mutable (through `c`) and as immutable (through `b`) at the same time."
@@ -7722,7 +7722,7 @@ msgstr "// Не срабатывает (не найдено)\n"
#: src/borrowing/exercise.md
msgid "The goal of this exercise is to practice the core concepts of ownership and borrowing, specifically the rule that you cannot mutate a collection while holding a reference to one of its elements."
-msgstr "Цель этого упражнения --- попрактиковать базовые концепции владения и заимствования, в частности правило, что нельзя изменять коллекцию, удерживая ссылку на один из её элементов."
+msgstr "Цель этого упражнения --- отработать базовые концепции владения и заимствования, в частности правило, что нельзя изменять коллекцию, удерживая ссылку на один из её элементов."
#: src/borrowing/exercise.md
msgid "`add_spell` should take ownership of a `Spell` and move it into the `Wizard`'s inventory."
@@ -7778,7 +7778,7 @@ msgstr "Заимствование в функциях"
#: src/lifetimes/simple-borrows.md
msgid "As part of borrow checking, the compiler needs to reason about how borrows flow into and out of functions. In the simplest case borrows last for the duration of the function call:"
-msgstr "В рамках проверки заимствований компилятору нужно понимать, как заимствования передаются в функции и из них. В простейшем случае заимствования существуют в течение вызова функции:"
+msgstr "При анализе заимствований компилятору нужно понимать, как заимствования передаются в функции и из них. В простейшем случае заимствования существуют в течение вызова функции:"
#: src/lifetimes/simple-borrows.md
msgid "// Borrow `val` for the function call.\n"
@@ -7806,7 +7806,7 @@ msgstr "Функции Rust могут возвращать ссылки, то
#: src/lifetimes/returning-borrows.md
msgid "If a function returns a reference (or another kind of borrow), it was likely derived from one of its arguments. This means that the return value of the function will extend the borrow for one or more argument borrows."
-msgstr "Если функция возвращает ссылку (или другой вид заимствования), она, скорее всего, выведена из одного из аргументов. Это значит, что возвращаемое значение функции продлит заимствование одного или нескольких аргументов."
+msgstr "Если функция возвращает ссылку (или другой вид заимствования), она, скорее всего, получена из одного из аргументов. Это значит, что возвращаемое значение функции продлит заимствование одного или нескольких аргументов."
#: src/lifetimes/returning-borrows.md
msgid "This case is still fairly simple, in that only one borrow is passed into the function, so the returned borrow has to be the same one."
@@ -8790,7 +8790,7 @@ msgstr "Перечисления не поддерживают приватно
#: src/modules/encapsulation.md
msgid "If students want more information about privacy (or lack thereof) in enums, you can bring up `#[doc_hidden]` and `#[non_exhaustive]` and show how they're used to limit what can be done with an enum."
-msgstr "Если студенты хотят узнать больше о приватности (или её отсутствии) в перечислениях, можно упомянуть `#[doc_hidden]` и `#[non_exhaustive]` и показать, как их используют, чтобы ограничить то, что можно делать с перечислением."
+msgstr "Если студенты хотят узнать больше о приватности (или её отсутствии) в перечислениях, можно упомянуть `#[doc(hidden)]` и `#[non_exhaustive]` и показать, как их используют, чтобы ограничить то, что можно делать с перечислением."
#: src/modules/encapsulation.md
msgid "Module privacy still applies when there are `impl` blocks in other modules [(example in the playground)](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=3e61f43c88de12bcdf69c1d6df9ab3da)."
@@ -9028,7 +9028,7 @@ msgstr "Привет, мир!"
#: src/testing/unit-tests.md
msgid "This lets you unit test private helpers."
-msgstr "Это позволяет тестировать модулем приватные вспомогательные функции."
+msgstr "Это позволяет модульно тестировать приватные вспомогательные функции."
#: src/testing/unit-tests.md
msgid "The `#[cfg(test)]` attribute is only active when you run `cargo test`."
@@ -9118,7 +9118,7 @@ msgstr "[Алгоритм Луна](https://en.wikipedia.org/wiki/Luhn_algorithm
#: src/testing/exercise.md
msgid "Ignore all spaces. Reject numbers with fewer than two digits. Reject letters and other non-digit characters."
-msgstr "Игнорируйте все пробелы. Отвергайте числа с менее чем двумя цифрами. Отвергайте буквы и другие нецифровые символы."
+msgstr "Игнорируйте все пробелы. Отвергайте числа, в которых меньше двух цифр. Отвергайте буквы и другие нецифровые символы."
#: src/testing/exercise.md
msgid "Moving from **right to left**, double every second digit: for the number `1234`, we double `3` and `1`. For the number `98765`, we double `6` and `8`."
@@ -9542,7 +9542,7 @@ msgstr "`anyhow::Context` --- трейт, реализованный для ст
#: src/error-handling/anyhow.md
msgid "`anyhow::Error` has support for downcasting, much like `std::any::Any`; the specific error type stored inside can be extracted for examination if desired with [`Error::downcast`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html#method.downcast)."
-msgstr "`anyhow::Error` поддерживает даункастинг, похожий на `std::any::Any`: при желании можно извлечь конкретный тип ошибки, хранящийся внутри, для проверки с помощью [`Error::downcast`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html#method.downcast)."
+msgstr "`anyhow::Error` поддерживает приведение к конкретному типу (downcast), как `std::any::Any`: при желании можно извлечь конкретный тип ошибки, хранящийся внутри, для проверки с помощью [`Error::downcast`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html#method.downcast)."
#: src/error-handling/exercise.md
msgid "In this exercise we're revisiting the expression evaluator exercise that we did in day 2. Our initial solution ignores a possible error case: Dividing by zero! Rewrite `eval` to instead use idiomatic error handling to handle this error case and return an error when it occurs. We provide a simple `DivideByZeroError` type to use as the error type for `eval`."
@@ -10337,7 +10337,7 @@ msgstr "Код на следующих страницах можно найти
#: src/android/setup.md
msgid "Cuttlefish is a reference Android device designed to work on generic Linux desktops. MacOS support is also planned."
-msgstr "Cuttlefish --- эталонное устройство Android, рассчитанное на работу в обычных Linux-рабочих станциях. Поддержка macOS также планируется."
+msgstr "Cuttlefish --- эталонное устройство Android, рассчитанное на работу на обычных рабочих станциях с Linux. Поддержка macOS также планируется."
#: src/android/setup.md
msgid "The Cuttlefish system image maintains high fidelity to real devices, and is the ideal emulator to run many Rust use cases."
@@ -10393,7 +10393,7 @@ msgstr "`rust_test`"
#: src/android/build-rules.md
msgid "Produces a Rust test binary that uses the standard Rust test harness."
-msgstr "Создаёт бинарный файл тестов Rust, который использует стандартный харнесс тестов Rust."
+msgstr "Создаёт бинарный файл тестов Rust, который использует стандартную тестовую обвязку (test harness) Rust."
#: src/android/build-rules.md
msgid "`rust_fuzz`"
@@ -10527,7 +10527,7 @@ msgstr "`libgreeting`, которую мы определим ниже,"
#: src/android/build-rules/library.md
msgid "`libtextwrap`, which is a crate already vendored in [`external/rust/android-crates-io/crates/`](https://cs.android.com/android/platform/superproject/main/+/main:external/rust/android-crates-io/crates/)."
-msgstr "`libtextwrap`, которая уже вендорена как крейт в [`external/rust/android-crates-io/crates/`](https://cs.android.com/android/platform/superproject/main/+/main:external/rust/android-crates-io/crates/)."
+msgstr "`libtextwrap`, которая уже включена в дерево исходников как крейт в [`external/rust/android-crates-io/crates/`](https://cs.android.com/android/platform/superproject/main/+/main:external/rust/android-crates-io/crates/)."
#: src/android/build-rules/library.md
msgid "\"hello_rust_with_dep\""
@@ -11539,7 +11539,7 @@ msgstr "Мы уже видели это в [упражнении «Безопа
#: src/android/interoperability/with-c.md
msgid "This assumes full knowledge of the target platform. Not recommended for production."
-msgstr "Это предполагает полное знание целевой платформы. Не рекомендуется для производственного кода."
+msgstr "Это предполагает полное знание целевой платформы. Не рекомендуется для рабочего кода."
#: src/android/interoperability/with-c.md
msgid "We will look at better options next."
@@ -12241,7 +12241,7 @@ msgstr "Добро пожаловать в Rust в Chromium"
#: src/chromium.md
msgid "Rust is supported for third-party libraries in Chromium, with first-party glue code to connect between Rust and existing Chromium C++ code."
-msgstr "Rust поддерживается для сторонних библиотек в Chromium, а код-клей (glue code) первой стороны связывает Rust с существующим C++-кодом Chromium."
+msgstr "Rust поддерживается для сторонних библиотек в Chromium, а собственный клей-код (glue code) связывает Rust с существующим C++-кодом Chromium."
#: src/chromium.md
msgid "Today, we'll call into Rust to do something silly with strings. If you've got a corner of the code where you're displaying a UTF-8 string to the user, feel free to follow this recipe in your part of the codebase instead of the exact part we talk about."
@@ -12655,7 +12655,7 @@ msgstr "Откройте `components/qr_code_generator/qr_code_generator_ffi_glu
#: src/chromium/build-rules/vscode.md
msgid "Place the cursor over the `QrCode::new` call (around line 26) in \\`qr_code_generator_ffi_glue.rs"
-msgstr "Поставьте курсор на вызов `QrCode::new` (примерно в строке 26) в \\`qr_code_generator_ffi_glue.rs"
+msgstr "Поставьте курсор на вызов `QrCode::new` (примерно в строке 26) в `qr_code_generator_ffi_glue.rs`"
#: src/chromium/build-rules/vscode.md
msgid "Demo **show documentation** (typical bindings: vscode = ctrl k i; vim/CoC = K)."
@@ -12699,7 +12699,7 @@ msgstr "Добавьте эту новую цель Rust как зависимо
#: src/exercises/chromium/build-rules.md
msgid "Call this function from somewhere in `ui/base/resource/resource_bundle.cc` - we suggest the top of `ResourceBundle::MaybeMangleLocalizedString`. Build and run Chromium, and ensure that \"Hello from Rust!\" is printed lots of times."
-msgstr "Вызовите эту функцию откуда-нибудь из `ui/base/resource/resource_bundle.cc` --- предлагаем начало `ResourceBundle::MaybeMangleLocalizedString`. Соберите и запустите Chromium и убедитесь, что \"Hello from Rust!\" выводится много раз."
+msgstr "Вызовите эту функцию откуда-нибудь из `ui/base/resource/resource_bundle.cc` --- предлагаем начало `ResourceBundle::MaybeMangleLocalizedString`. Соберите и запустите Chromium и убедитесь, что «Hello from Rust!» выводится много раз."
#: src/exercises/chromium/build-rules.md
msgid "If you use VSCode, now set up Rust to work well in VSCode. It will be useful in subsequent exercises. If you've succeeded, you will be able to use right-click \"Go to definition\" on `println!`."
@@ -13708,7 +13708,7 @@ msgstr "**Важно:** нужно использовать `git add -f`, ина
#: src/chromium/adding-third-party-crates/checking-in.md
msgid "As you do so, you might find presubmit checks fail because of non-inclusive language. This is because Rust crate data tends to include names of git branches, and many projects still use non-inclusive terminology there. So you may need to run:"
-msgstr "При этом могут сработать предварительные проверки (presubmit) из-за не-инклюзивного языка. Дело в том, что данные крейтов Rust часто содержат имена git-веток, а во многих проектах там до сих пор используется не-инклюзивная терминология. Поэтому может понадобиться выполнить:"
+msgstr "При этом могут сработать предварительные проверки (presubmit) из-за неинклюзивной лексики. Дело в том, что данные крейтов Rust часто содержат имена git-веток, а во многих проектах там до сих пор используется неинклюзивная терминология. Поэтому может понадобиться выполнить:"
#: src/chromium/adding-third-party-crates/keeping-up-to-date.md
msgid "As the OWNER of any third party Chromium dependency, you are [expected to keep it up to date with any security fixes](https://chromium.googlesource.com/chromium/src/+/main/docs/adding_to_third_party.md#add-owners). It is hoped that we will soon automate this for Rust crates, but for now, it's still your responsibility just as it is for any other third party dependency."
@@ -14196,7 +14196,7 @@ msgstr "// pin_input.is_high(); // Ошибка, значение перемещ
#: src/bare-metal/microcontrollers/type-state.md
msgid "Pins don't implement `Copy` or `Clone`, so only one instance of each can exist. Once a pin is moved out of the port struct, nobody else can take it."
-msgstr "Выводы не реализуют `Copy` или `Clone`, поэтому каждый экземпляр может существовать только в одном экземпляре. Как только вывод перемещён из структуры порта, никто другой не может его забрать."
+msgstr "Выводы не реализуют `Copy` или `Clone`, поэтому каждый вывод может существовать только в единственном экземпляре. Как только вывод перемещён из структуры порта, никто другой не может его забрать."
#: src/bare-metal/microcontrollers/type-state.md
msgid "Changing the configuration of a pin consumes the old pin instance, so you can't use the old instance afterwards."
@@ -15564,7 +15564,7 @@ msgstr "Инициализация, драйвер UART, простой загр
#: src/bare-metal/aps/other-projects.md
msgid "Some caveats around cache maintenance and initialization in Rust, not necessarily a good example to copy for production code."
-msgstr "Некоторые оговорки относительно обслуживания кэша и инициализации в Rust; это не обязательно хороший пример для копирования в производственный код."
+msgstr "Некоторые оговорки относительно обслуживания кэша и инициализации в Rust; это не обязательно хороший пример для копирования в рабочий код."
#: src/bare-metal/aps/other-projects.md
msgid "[`cargo-call-stack`](https://crates.io/crates/cargo-call-stack)"
@@ -17031,7 +17031,7 @@ msgstr "Крейт [Flume](https://docs.rs/flume/latest/flume/) содержит
#: src/concurrency/async-control-flow/channels.md
msgid "What makes working with `async` channels preferable is the ability to combine them with other `future`s to combine them and create complex control flow."
-msgstr "Работа с асинхронными каналами удобнее благодаря возможности комбинировать их с другими `future`, чтобы создавать сложный поток управления."
+msgstr "Работа с асинхронными каналами удобнее благодаря возможности комбинировать их с другими фьючерсами, чтобы создавать сложный поток управления."
#: src/concurrency/async-control-flow/join.md
msgid "A join operation waits until all of a set of futures are ready, and returns a collection of their results. This is similar to `Promise.all` in JavaScript or `asyncio.gather` in Python."
@@ -17639,7 +17639,7 @@ msgstr "Сделайте ваш API предсказуемым"
#: src/idiomatic/welcome.md
msgid "Follow naming conventions (case conventions, prefer vocabulary precedented in the standard library - e.g., methods should be called \"push\" not \"push_back\", \"is_empty\" not \"empty\" etc.)"
-msgstr "Следуйте соглашениям об именовании (регистр и привычная лексика стандартной библиотеки: например, методы должны называться \"push\", а не \"push_back\", \"is_empty\", а не \"empty\" и т. д.)"
+msgstr "Следуйте соглашениям об именовании (регистр и привычная лексика стандартной библиотеки: например, методы должны называться «push», а не «push_back», «is_empty», а не «empty» и т. д.)"
#: src/idiomatic/welcome.md
msgid "Know the vocabulary types and traits in the standard library, and use them in your APIs. If something feels like a basic type/algorithm, check in the standard library first."
@@ -17959,7 +17959,7 @@ msgstr "Вы, возможно, видели подробную документ
#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md
msgid "Fundamental library code often has elaborate documentation, for example, the standard library, highly reusable frameworks like Serde and Tokio. Teams responsible for this code often have appropriate resources to write and maintain elaborate documentation."
-msgstr "Фундаментальный библиотечный код часто имеет подробную документацию, например стандартная библиотека и высокоповторно используемые фреймворки вроде Serde и Tokio. Команды, отвечающие за такой код, обычно имеют ресурсы, чтобы писать и поддерживать подробную документацию."
+msgstr "Фундаментальный библиотечный код часто имеет подробную документацию, например стандартная библиотека и многократно переиспользуемые фреймворки вроде Serde и Tokio. Команды, отвечающие за такой код, обычно имеют ресурсы, чтобы писать и поддерживать подробную документацию."
#: src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md
msgid "Library code is often stable, so the community is going to extract a significant benefit from elaborate documentation before it needs to be reworked."
@@ -18163,7 +18163,7 @@ msgstr "Называйте ключевые слова ближе к начал
#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md
msgid "This aids skimming and scanning, as the first few words of a paragraph stand out the most."
-msgstr "Это помогает при бегло просмотре, так как первые несколько слов абзаца выделяются больше всего."
+msgstr "Это помогает при беглом просмотре, так как первые несколько слов абзаца выделяются больше всего."
#: src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md
msgid "Skimming and scanning lets users quickly navigate a text, keeping keywords as close to the beginning of a paragraph as possible lets a user determine if they've found relevant information faster."
@@ -18335,7 +18335,7 @@ msgid ""
"/// Returns a future that resolves when operation completes. \n"
msgstr ""
"// плохо\n"
-"/// Возвращает future, который завершается при завершении операции. \n"
+"/// Возвращает фьючерс, который завершается при завершении операции. \n"
#: src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md
msgid ""
@@ -19119,7 +19119,7 @@ msgstr "Это не значит, что равенство вызовет па
#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md
msgid "For example, with floating point values `NaN` is an outlier: `NaN == NaN` is false, despite bitwise equality."
-msgstr "Например, для значений с плавающей запятой `NaN` --- выброс: `NaN == NaN` ложно, несмотря на побитовое равенство."
+msgstr "Например, для значений с плавающей запятой `NaN` --- исключение: `NaN == NaN` ложно, несмотря на побитовое равенство."
#: src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md
msgid "`PartialEq` exists to separate types like `f32`/`f64` from types with Total Equality."
@@ -19795,7 +19795,7 @@ msgstr "Пример выше показывает упрощённый `Mutex`
#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md
msgid "Even though it is not a production-ready implementation, it illustrates the core idea:"
-msgstr "Хотя это не готовая к производству реализация, она иллюстрирует основную идею:"
+msgstr "Хотя это не промышленная реализация, она иллюстрирует основную идею:"
#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md
msgid "the guard represents exclusive access,"
@@ -19831,7 +19831,7 @@ msgstr "Полностью блокирующий метод `.lock()` и неб
#: src/idiomatic/leveraging-the-type-system/raii/drop_guards.md
msgid "You can explore the [`Mutex` implementation in Rust’s std library](https://doc.rust-lang.org/std/sync/struct.Mutex.html) as an example of a production-ready mutex. The [`Mutex` from the `parking_lot` crate](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html) is another worthwhile reference."
-msgstr "Можно изучить [реализацию `Mutex` в стандартной библиотеке Rust](https://doc.rust-lang.org/std/sync/struct.Mutex.html) как пример готового к производству мьютекса. Ещё один полезный источник --- [`Mutex` из крейта `parking_lot`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html)."
+msgstr "Можно изучить [реализацию `Mutex` в стандартной библиотеке Rust](https://doc.rust-lang.org/std/sync/struct.Mutex.html) как пример промышленной реализации мьютекса. Ещё один полезный источник --- [`Mutex` из крейта `parking_lot`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html)."
#: src/idiomatic/leveraging-the-type-system/raii/drop_bomb.md
msgid "Drop Bombs: Enforcing API Correctness"
@@ -23468,10 +23468,10 @@ msgid ""
"```"
msgstr ""
"```console\n"
-"$ git clone --depth=1 https://github.com/r007/EmbeddedRust-Rus/tree/main/comprehensive-rust\n"
-"Cloning into 'comprehensive-rust'...\n"
+"$ git clone --depth=1 https://github.com/r007/EmbeddedRust-Rus.git\n"
+"Cloning into 'EmbeddedRust-Rus'...\n"
"...\n"
-"$ cd comprehensive-rust\n"
+"$ cd EmbeddedRust-Rus/comprehensive-rust\n"
"$ cargo install-tools\n"
"...\n"
"$ cargo serve # затем откройте http://127.0.0.1:3000/ в браузере\n"
@@ -24825,7 +24825,7 @@ msgstr "Нужны исправления в `main`."
#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md
msgid "`a` does not satisfy one of the preconditions of `copy` (source\\` data ends with a null byte within its memory allocation)"
-msgstr "`a` не удовлетворяет одному из предусловий `copy` (данные source\\` должны заканчиваться нулевым байтом внутри своего выделения памяти)"
+msgstr "`a` не удовлетворяет одному из предусловий `copy` (данные `source` должны заканчиваться нулевым байтом внутри своего выделения памяти)"
#: src/unsafe-deep-dive/rules-of-the-game/copying-memory/documented-safety-preconditions.md
msgid "SAFETY comment needed"
@@ -25121,7 +25121,7 @@ msgstr "Вопрос: «Хотя память была записана, тип
#: src/unsafe-deep-dive/initialization/maybeuninit/zeroed-method.md
msgid "A: Some types require their values to be non-zero or non-null. The classic case is references, but this applies to many other types as well. Consider the `NonZeroUsize` integer type and others in its family."
-msgstr "Ответ: некоторым типам их значения должны быть ненулевыми или не-null. Классический случай — ссылки, но это относится и ко многим другим типам. Вспомните целочисленный тип `NonZeroUsize` и другие типы этого семейства."
+msgstr "Ответ: значения некоторых типов не могут быть нулевыми (null). Классический случай — ссылки, но это относится и ко многим другим типам. Вспомните целочисленный тип `NonZeroUsize` и другие типы этого семейства."
#: src/unsafe-deep-dive/initialization/maybeuninit/write-vs-assignment.md
msgid "MaybeUninit.write() vs assignment"
@@ -25513,7 +25513,7 @@ msgstr "Спросите: какие типы могут быть `!Unpin`?"
#: src/unsafe-deep-dive/pinning/unpin-trait.md
msgid "Compiler-generated futures"
-msgstr "Футуры, сгенерированные компилятором"
+msgstr "Фьючерсы, сгенерированные компилятором"
#: src/unsafe-deep-dive/pinning/unpin-trait.md
msgid "Types containing a `PhantomPinned` field"
@@ -25657,7 +25657,7 @@ msgstr ""
#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-offset.md
msgid "With Offset"
-msgstr "С смещением (Offset)"
+msgstr "Со смещением (Offset)"
#: src/unsafe-deep-dive/pinning/self-referential-buffer/rust-offset.md
msgid "In Rust, it's more idiomatic to use an offset variable and to create references on-demand."
@@ -26828,7 +26828,7 @@ msgid ""
"receiver: \n"
"The first parameter in a Rust [method](methods-and-traits/methods.md) that represents the instance on which the method is called."
msgstr ""
-"приёмник:\n"
+"получатель:\n"
"Первый параметр [метода](methods-and-traits/methods.md) в Rust, который представляет экземпляр, для которого вызван метод."
#: src/glossary.md
@@ -26917,7 +26917,7 @@ msgid ""
"A function that tests the correctness of other code. Rust has a built-in test runner. See [Testing](testing.md)."
msgstr ""
"тест:\n"
-"Функция, которая проверяет корректность другого кода. В Rust есть встроенный запускатель тестов. См. [Тестирование](testing.md)."
+"Функция, которая проверяет корректность другого кода. В Rust есть встроенное средство запуска тестов. См. [Тестирование](testing.md)."
#: src/glossary.md
msgid ""
@@ -27105,7 +27105,7 @@ msgstr "[Ferrous Teaching Material](https://ferrous-systems.github.io/teaching-m
#: src/other-resources.md
msgid "[Advanced testing for Rust applications](https://rust-exercises.com/advanced-testing/): a self-paced workshop that goes beyond Rust's built-in testing framework. It covers `googletest`, snapshot testing, mocking as well as how to write your own custom test harness."
-msgstr "[Advanced testing for Rust applications](https://rust-exercises.com/advanced-testing/): самостоятельный практикум, выходящий за рамки встроенного фреймворка тестирования Rust. Рассматриваются `googletest`, снапшот-тестирование, моки, а также написание собственного тестового харнесса."
+msgstr "[Advanced testing for Rust applications](https://rust-exercises.com/advanced-testing/): самостоятельный практикум, выходящий за рамки встроенного фреймворка тестирования Rust. Рассматриваются `googletest`, снапшот-тестирование, моки, а также написание собственной тестовой обвязки (test harness)."
#: src/other-resources.md
msgid "[Beginner's Series to Rust](https://docs.microsoft.com/en-us/shows/beginners-series-to-rust/) and [Take your first steps with Rust](https://docs.microsoft.com/en-us/learn/paths/rust-first-steps/): two Rust guides aimed at new developers. The first is a set of 35 videos and the second is a set of 11 modules which covers Rust syntax and basic constructs."
diff --git a/discovery-mb2/src/01-background/README.md b/discovery-mb2/src/01-background/README.md
index c0a74ea..6a3213b 100644
--- a/discovery-mb2/src/01-background/README.md
+++ b/discovery-mb2/src/01-background/README.md
@@ -32,7 +32,7 @@
* *Отзывчивость:* для выполнения своей задачи некоторым встраиваемым системам нужно всегда реагировать в ограниченный промежуток времени (например, антиблокировочная система тормозов автомобиля). Если система не уложится в такой *срок*, может произойти катастрофический отказ. Такое требование называют «жёстким реальным временем» (hard real time), а встраиваемую систему, которая связана таким сроком, — «системой жёсткого реального времени». У компьютера общего назначения с ОС обычно много программных компонентов, которые делят между собой вычислительные ресурсы. Из-за этого труднее гарантировать выполнение программы в жёстких временных рамках.
- * *Надёжность.* В системах с меньшим числом компонентов (как аппаратных, так и программных) меньше возможностей для сбоя!
+ * *Надёжность:* в системах с меньшим числом компонентов (как аппаратных, так и программных) меньше возможностей для сбоя!
* **Когда *не* стоит использовать микроконтроллер?**
@@ -42,7 +42,7 @@
Некоторые микроконтроллеры не имеют аппаратной поддержки операций с плавающей точкой. На таких устройствах сложение двух чисел одинарной точности может занять сотни тактов процессора.
- Наконец, памяти у микроконтроллеров обычно немного. Её может быть всего 16 КБ для инструкций программы и 4 КБ для данных, что делает программирование для таких систем довольно непростым. Объём встроенной памяти на единицу стоимости и энергопотребления постоянно растёт, но процессор, с которым мы будем работать, по-прежнему располагает «всего лишь» 512 КБ памяти для инструкций и 256 КБ для данных — гораздо меньше, чем у «настоящего компьютера».
+ Наконец, памяти у микроконтроллеров обычно немного. Её может быть всего 16 КБ для инструкций программы и 4 КБ для данных, что делает программирование для таких систем довольно непростым. Объём встроенной памяти на единицу стоимости и энергопотребления постоянно растёт, но процессор, с которым мы будем работать, по-прежнему располагает «всего лишь» 512 КБ памяти для инструкций и 128 КБ для данных — гораздо меньше, чем у «настоящего компьютера».
* **Почему Rust, а не C?**
diff --git a/discovery-mb2/src/03-setup/IDE.md b/discovery-mb2/src/03-setup/IDE.md
index 11eb5f4..af03d3b 100644
--- a/discovery-mb2/src/03-setup/IDE.md
+++ b/discovery-mb2/src/03-setup/IDE.md
@@ -13,4 +13,4 @@
При редактировании конфигурации сборки IntelliJ вот несколько значений, отличающихся от стандартных:
* Нужно изменить команду. Когда книга предлагает выполнить `cargo embed FLAGS`, замените стандартное значение `run` на команду `embed FLAGS`,
* Нужно включить «Emulate terminal in output console». Иначе программа не сможет выводить текст в терминал.
-* Убедитесь, что рабочий каталог — `microbit/src/N-name`, где `N-name` — каталог главы, которую вы читаете. Запускать из каталога `src` нельзя, так как в нём нет файла Cargo.
+* Убедитесь, что рабочий каталог — `discovery-mb2/src/N-name`, где `N-name` — каталог главы, которую вы читаете. Запускать из каталога `src` нельзя, так как в нём нет файла Cargo.
diff --git a/discovery-mb2/src/03-setup/README.md b/discovery-mb2/src/03-setup/README.md
index ffb6eff..87c4d77 100644
--- a/discovery-mb2/src/03-setup/README.md
+++ b/discovery-mb2/src/03-setup/README.md
@@ -84,7 +84,7 @@ cargo-embed 0.24.0 (git commit: crates.io)
Книга также содержит небольшие проекты на Rust, которые используются в разных главах. Проще всего воспользоваться ими, скачав исходный код книги. Сделать это можно одним из следующих способов:
-- Откройте [репозиторий](https://github.com/r007/EmbeddedRust-Rus/tree/main/discovery-mb2), нажмите зелёную кнопку «Code», а затем «Download Zip».
+- Откройте [репозиторий](https://github.com/r007/EmbeddedRust-Rus), нажмите зелёную кнопку «Code», а затем «Download ZIP». Книга находится в каталоге `discovery-mb2`.
- Склонируйте его с помощью `git` (если вы знаете `git`, он у вас, скорее всего, уже установлен) из того же репозитория, который указан выше для ZIP-архива.
diff --git a/discovery-mb2/src/03-setup/linux.md b/discovery-mb2/src/03-setup/linux.md
index 747db2a..86b6baa 100644
--- a/discovery-mb2/src/03-setup/linux.md
+++ b/discovery-mb2/src/03-setup/linux.md
@@ -29,7 +29,7 @@ $ sudo pacman -S arm-none-eabi-gdb minicom libunwind
> **ПРИМЕЧАНИЕ** `arm-none-eabi-gdb` — это команда GDB, которой вы будете отлаживать программы для Arm Cortex-M.
-Если для вашего дистрибутива нет пакетов [готового набора инструментов Arm](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads), скачайте файл «Linux 64-bit» и добавьте его каталог `bin` в `PATH`. Вот один из способов:
+Если для вашего дистрибутива нет пакетов [готового тулчейна Arm](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads), скачайте файл «Linux 64-bit» и добавьте его каталог `bin` в `PATH`. Вот один из способов:
``` console
$ mkdir -p ~/local
diff --git a/discovery-mb2/src/03-setup/verify.md b/discovery-mb2/src/03-setup/verify.md
index 83bff38..3030708 100644
--- a/discovery-mb2/src/03-setup/verify.md
+++ b/discovery-mb2/src/03-setup/verify.md
@@ -48,7 +48,7 @@ Debugging RISC-V targets over SWD is not supported. For these targets, JTAG is t
Debugging Xtensa targets over SWD is not supported. For these targets, JTAG is the only supported protocol. Xtensa specific information cannot be printed.
```
-Затем убедитесь, что вы находитесь в каталоге `src/03-setup` исходного кода книги, и выполните команды:
+Затем убедитесь, что вы находитесь в каталоге `discovery-mb2/src/03-setup` исходного кода книги, и выполните команды:
```
$ rustup target add thumbv7em-none-eabihf
diff --git a/discovery-mb2/src/04-meet-your-hardware/microbit-v2.md b/discovery-mb2/src/04-meet-your-hardware/microbit-v2.md
index b79b349..da82d88 100644
--- a/discovery-mb2/src/04-meet-your-hardware/microbit-v2.md
+++ b/discovery-mb2/src/04-meet-your-hardware/microbit-v2.md
@@ -1,8 +1,8 @@
# Nordic nRF52833 («nRF52», micro:bit v2)
-Под нашим MCU находятся 73 крошечных металлических **пина** (это так называемый чип [aQFN73]). Эти пины соединены с **дорожками** — маленькими «дорогами», которые служат проводами, соединяющими компоненты на плате. MCU может динамически менять электрические свойства пинов. Это работает примерно как выключатель света: меняется то, как электрический ток проходит по цепи. Включая или выключая ток через конкретный пин, можно зажигать и гасить светодиод, подключённый к этому пину (через дорожки).
+Под нашим MCU находятся 73 крошечных металлических **вывода** (это так называемый чип [aQFN73]). Эти выводы соединены с **дорожками** — маленькими «дорогами», которые служат проводами, соединяющими компоненты на плате. MCU может динамически менять электрические свойства выводов. Это работает примерно как выключатель света: меняется то, как электрический ток проходит по цепи. Включая или выключая ток через конкретный вывод, можно зажигать и гасить светодиод, подключённый к этому выводу (через дорожки).
-Каждый производитель использует собственную схему обозначений, но по номеру детали часто можно узнать о компоненте многое. Номер детали нашего MCU — `N52833 QIAAA0 2024AL`. Невооружённым глазом его, скорее всего, не разглядеть, но он нанесён на чип. (Если у вас более поздняя ревизия MB2, номер может немного отличаться. Это не проблема, но часть `N52833` должна присутствовать.) Буква `N` в начале подсказывает, что деталь выпущена компанией [Nordic Semiconductor]. Найдя номер детали на их сайте, мы быстро попадаем на [страницу продукта]. Там мы узнаём, что главная особенность чипа — это «Bluetooth Low Energy и 2.4 GHz SoC» (SoC — «system on a chip», «система на кристалле»), что объясняет и RF в названии: RF — это радиочастота (radio frequency). Если немного поискать в документации чипа, то на [страницу продукта] ведёт ссылка на [спецификацию продукта]. В ней глава 10, «Ordering Information», посвящена расшифровке странного обозначения чипа. Там мы узнаём следующее:
+Каждый производитель использует собственную схему обозначений, но по номеру детали часто можно узнать о компоненте многое. Номер детали нашего MCU — `N52833 QIAAA0 2024AL`. Невооружённым глазом его, скорее всего, не разглядеть, но он нанесён на чип. (Если у вас более поздняя ревизия MB2, номер может немного отличаться. Это не проблема, но часть `N52833` должна присутствовать.) Буква `N` в начале подсказывает, что деталь выпущена компанией [Nordic Semiconductor]. Найдя номер детали на их сайте, мы быстро попадаем на [страницу продукта]. Там мы узнаём, что главная особенность чипа — это «Bluetooth Low Energy и 2.4 GHz SoC» (SoC — «system on a chip», «система на кристалле»), что объясняет и RF в названии: RF — это радиочастота (radio frequency). Если немного поискать, на [странице продукта] обнаружится ссылка на [спецификацию продукта]. В ней глава 10, «Ordering Information», посвящена расшифровке странного обозначения чипа. Там мы узнаём следующее:
[aQFN73]: https://en.wikipedia.org/wiki/Flat_no-leads_package
[Nordic Semiconductor]: https://www.nordicsemi.com/
diff --git a/discovery-mb2/src/04-meet-your-hardware/terminology.md b/discovery-mb2/src/04-meet-your-hardware/terminology.md
index bdb8335..cddf5af 100644
--- a/discovery-mb2/src/04-meet-your-hardware/terminology.md
+++ b/discovery-mb2/src/04-meet-your-hardware/terminology.md
@@ -26,7 +26,7 @@
## Объединение уровней
-Далее рассмотрим очень важную часть программного обеспечения в экосистеме Rust Embedded: [`embedded-hal`]. Как следует из названия, она относится ко второму уровню абстракции, с которым мы уже познакомились: к HAL. Идея [`embedded-hal`] — предоставить набор трейтов, описывающих поведение, которое обычно общее для всех реализаций конкретной периферии во всех HAL. Например, всегда ожидаешь функций, которые могут включать или выключать питание пина: например, чтобы включить и выключить светодиод на плате или что-то подобное.
+Далее рассмотрим очень важную часть программного обеспечения в экосистеме Rust Embedded: [`embedded-hal`]. Как следует из названия, она относится ко второму уровню абстракции, с которым мы уже познакомились: к HAL. Идея [`embedded-hal`] — предоставить набор трейтов, описывающих поведение, которое обычно общее для всех реализаций конкретной периферии во всех HAL. Например, почти всегда нужны функции, которые включают и выключают вывод (скажем, чтобы зажечь и погасить светодиод на плате).
`embedded-hal` позволяет написать драйвер для какого-либо устройства, например датчика температуры, который можно использовать на любом чипе, для которого существует реализация трейтов [`embedded-hal`]. Этого добиваются, написав драйвер так, чтобы он опирался только на трейты [`embedded-hal`]. Такие драйверы называют *не зависящими от платформы* (platform-agnostic). К счастью для нас, драйверы, которые мы будем брать с `crates.io`, почти все не зависят от платформы.
diff --git a/discovery-mb2/src/05-meet-your-software/README.md b/discovery-mb2/src/05-meet-your-software/README.md
index 089f336..ba93427 100644
--- a/discovery-mb2/src/05-meet-your-software/README.md
+++ b/discovery-mb2/src/05-meet-your-software/README.md
@@ -2,13 +2,13 @@
В этой главе мы научимся собирать, запускать и отлаживать несколько *очень* простых программ. Цель — не углубляться в детали программирования MB2 на Rust (пока), а просто освоить сам процесс.
-Сначала короткое пояснение об условных обозначениях, которые используются в остальной части книги. Предполагается, что вы получите копию всей книги с помощью команды:
+Сначала короткое пояснение об условных обозначениях, которые используются в остальной части книги. Предполагается, что вы получите копию репозитория со всеми книгами сборника с помощью команды:
```
-git clone https://github.com/r007/EmbeddedRust-Rus/tree/main/discovery-mb2
+git clone https://github.com/r007/EmbeddedRust-Rus.git
```
-«Исходный код» книги находится в `discovery-mb2/mdbook/src`. Зайдите туда в своей копии и осмотритесь. В каталоге каждой главы есть и исходный текст в Markdown, *и* полный исходный код всех программ этой главы. Когда мы упоминаем путь вида `src/main.rs`, имеется в виду место относительно главы, с которой вы работаете. Например, в вашем `discovery-mb2` есть файл `mdbook/src/05-meet-your-software/examples/init.rs`. В этой главе мы будем называть его просто `examples/init.rs`.
+«Исходный код» книги находится в каталоге `discovery-mb2/src` этого репозитория. Зайдите туда в своей копии и осмотритесь. В каталоге каждой главы есть и исходный текст в Markdown, *и* полный исходный код всех программ этой главы. Когда мы упоминаем путь вида `src/main.rs`, имеется в виду место относительно главы, с которой вы работаете. Например, в вашей копии есть файл `discovery-mb2/src/05-meet-your-software/examples/init.rs`. В этой главе мы будем называть его просто `examples/init.rs`.
Есть два основных вида кода на Rust: исполняемые программы («binary») и библиотечный код («library»). Библиотечный код в этой книге большой роли играть не будет. Исходный код исполняемых программ может находиться в одном из нескольких мест:
diff --git a/discovery-mb2/src/05-meet-your-software/build-it.md b/discovery-mb2/src/05-meet-your-software/build-it.md
index 4f2021d..3aff5a0 100644
--- a/discovery-mb2/src/05-meet-your-software/build-it.md
+++ b/discovery-mb2/src/05-meet-your-software/build-it.md
@@ -26,7 +26,7 @@ $ rustup target add thumbv7em-none-eabihf
[проверке установки]: ../03-setup/verify.html#проверка-cargo-embed
-Когда компонент `rust-std` установлен, можно кросс-компилировать программу с помощью Cargo. Убедитесь, что вы находитесь в каталоге `mdbook/src/05-meet-your-software` репозитория Git, и выполните сборку. Этот начальный код — пример, поэтому собираем его как пример.
+Когда компонент `rust-std` установлен, можно кросс-компилировать программу с помощью Cargo. Убедитесь, что вы находитесь в каталоге `discovery-mb2/src/05-meet-your-software` репозитория Git, и выполните сборку. Этот начальный код — пример, поэтому собираем его как пример.
``` console
$ cargo build --example init
diff --git a/discovery-mb2/src/05-meet-your-software/debug-it.md b/discovery-mb2/src/05-meet-your-software/debug-it.md
index 7f64e11..68ce0fe 100644
--- a/discovery-mb2/src/05-meet-your-software/debug-it.md
+++ b/discovery-mb2/src/05-meet-your-software/debug-it.md
@@ -6,7 +6,7 @@
Прежде чем отлаживать программу, уделим минуту тому, чтобы понять, что здесь происходит. В предыдущей главе мы уже обсуждали назначение второго чипа на плате и то, как он общается с нашим компьютером, но как именно мы можем им воспользоваться?
-Небольшая опция `default.gdb.enabled = true` в `Embed.toml` заставила `cargo embed` после прошивки открыть так называемый «GDB-стаб». Это сервер, к которому может подключиться наш GDB и отправлять ему команды вроде «поставь точку останова по адресу X». Сервер сам решает, как обработать команду. В случае GDB-стаба `cargo embed` команда передаётся по USB «отладочному зонду» на втором чипе. Именно этот чип общается с MCU вместо нас.
+Небольшая опция `default.gdb.enabled = true` в `Embed.toml` заставила `cargo embed` после прошивки открыть так называемый «GDB-стаб». Это сервер, к которому может подключиться наш GDB и отправлять ему команды вроде «поставь точку останова по адресу X». Сервер сам решает, как обработать команду. В случае GDB-стаба `cargo embed` передаёт команду по USB «отладочному зонду» на втором чипе. Именно этот чип общается с MCU вместо нас.
## Начинаем отладку!
@@ -20,11 +20,11 @@ $ gdb ../../../target/thumbv7em-none-eabihf/debug/examples/init
[главу 3]: ../03-setup/index.md#инструменты
-Часть `../../..` в этой команде нужна, потому что каждый пример-проект находится в «workspace», который включает всю книгу. У workspace единый общий каталог `target`. Подробнее см. [в главе о workspace книги по Rust].
+Часть `../../..` в этой команде нужна, потому что каждый пример-проект входит в рабочее пространство (workspace), которое включает всю книгу. У него единый общий каталог `target`. Подробнее см. [в главе о рабочих пространствах книги по Rust].
> **ПРИМЕЧАНИЕ** Если `cargo-embed` выводит здесь много предупреждений, не беспокойтесь. На данный момент он не полностью реализует протокол GDB, поэтому может не распознать некоторые команды, которые ему отправляет GDB. Пока GDB не падает, всё в порядке.
-[в главе о workspace книги по Rust]: https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html#creating-a-workspace
+[в главе о рабочих пространствах книги по Rust]: https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html#creating-a-workspace
Теперь нужно подключиться к GDB-стабу. По умолчанию он работает на `localhost:1337`, поэтому для подключения выполните:
@@ -38,7 +38,7 @@ Remote debugging using :1337
> **ПРИМЕЧАНИЕ** Пример в репозитории для этой главы может со временем меняться. Поэтому номера строк и другие детали исходного кода могут отличаться от показанных здесь и ниже.
>
> Если программа не останавливается после запуска и вы оказываетесь где-то глубже в программе, как показано ниже, попробуйте выполнить `monitor reset halt`, чтобы сбросить её. Это связано с [ошибкой](https://github.com/probe-rs/probe-rs/issues/3438)
-> в `probe-rs`; подробности см. в [issue #27](https://github.com/r007/EmbeddedRust-Rus/issues/27).
+> в `probe-rs`; подробности см. в [issue #27](https://github.com/rust-embedded/discovery-mb2/issues/27).
> ```shell
> (gdb) target remote :1337
> Remote debugging using :1337
diff --git a/discovery-mb2/src/05-meet-your-software/embedded-setup.md b/discovery-mb2/src/05-meet-your-software/embedded-setup.md
index 0a4d1e7..360fbac 100644
--- a/discovery-mb2/src/05-meet-your-software/embedded-setup.md
+++ b/discovery-mb2/src/05-meet-your-software/embedded-setup.md
@@ -20,7 +20,7 @@
{{#include .cargo/config.toml}}
```
-Этот файл настраивает процесс линковки, подгоняя раскладку памяти программы под требования целевого устройства. Изменённый процесс линковки — требование крейта `cortex-m-rt`. Файл `.cargo/config.toml` также сообщает Cargo, как собирать и запускать код на нашем MB2.
+Этот файл настраивает процесс компоновки, подгоняя раскладку памяти программы под требования целевого устройства. Изменённый процесс линковки — требование крейта `cortex-m-rt`. Файл `.cargo/config.toml` также сообщает Cargo, как собирать и запускать код на нашем MB2.
Здесь также есть файл `Embed.toml`:
diff --git a/discovery-mb2/src/05-meet-your-software/light-it-up.md b/discovery-mb2/src/05-meet-your-software/light-it-up.md
index a4a9408..9da8cc7 100644
--- a/discovery-mb2/src/05-meet-your-software/light-it-up.md
+++ b/discovery-mb2/src/05-meet-your-software/light-it-up.md
@@ -1,12 +1,12 @@
# Зажигаем светодиод
-Закончим главу тем, что зажжём один из многочисленных светодиодов MB2. Для этого воспользуемся одним из трейтов, которые предоставляет `embedded-hal`, а именно трейтом [`OutputPin`], который позволяет включать и выключать пин.
+Закончим главу тем, что зажжём один из многочисленных светодиодов MB2. Для этого воспользуемся одним из трейтов, которые предоставляет `embedded-hal`, а именно трейтом [`OutputPin`], который позволяет включать и выключать вывод.
[`OutputPin`]: https://docs.rs/embedded-hal/0.2.6/embedded_hal/digital/v2/trait.OutputPin.html
## Светодиоды micro:bit
-На обратной стороне micro:bit видно квадрат 5×5 из светодиодов, который обычно называют матрицей светодиодов (LED matrix). Такое расположение позволяет обойтись не 25 отдельными пинами для управления каждым светодиодом, а всего 10 (5+5): ими задаётся, какой столбец и какая строка матрицы будут гореть.
+На обратной стороне micro:bit видно квадрат 5×5 из светодиодов, который обычно называют матрицей светодиодов (LED matrix). Такое расположение позволяет обойтись не 25 отдельными выводами для управления каждым светодиодом, а всего 10 (5+5): ими задаётся, какой столбец и какая строка матрицы будут гореть.
Пока для управления светодиодами мы будем использовать крейт `microbit-v2`. В [следующей главе] подробно разберём все доступные варианты.
@@ -22,17 +22,17 @@
Первые строки до функции `main` — это базовые импорты и настройка, с которыми мы в основном уже встречались. А вот функция `main` выглядит совсем иначе, чем всё, что мы видели до сих пор.
-Первая строка связана с тем, как устроены внутри большинство HAL, написанных на Rust. Как мы обсуждали ранее, они строятся поверх крейтов PAC, которые владеют (в смысле Rust) всей периферией чипа. Когда мы пишем
+Первая строка связана с внутренним устройством большинства HAL, написанных на Rust. Как мы обсуждали ранее, они строятся поверх крейтов PAC, которые владеют (в смысле Rust) всей периферией чипа. Когда мы пишем
let mut board = Board::take().unwrap();
мы забираем всю эту периферию у PAC и связываем её с переменной. В этом случае мы работаем не просто с HAL, а со всем BSP, поэтому вызов также забирает во владение Rust-представление других чипов на плате.
-> **ПРИМЕЧАНИЕ**: Если вам интересно, зачем здесь нужен `unwrap()`, то в теории `take()` может быть вызван более одного раза. Тогда периферия будет представлена двумя разными переменными, и две переменные будут менять один и тот же ресурс, что приведёт к путанице в поведении. Чтобы этого избежать, PAC реализованы так, что при повторном взятии периферии программа запаникует.
+> **ПРИМЕЧАНИЕ**: Если вам интересно, зачем здесь `unwrap()`: в теории `take()` может быть вызван более одного раза. Тогда периферия будет представлена двумя разными переменными, и две переменные будут менять один и тот же ресурс, что приведёт к путанице в поведении. Чтобы этого избежать, PAC реализованы так, что при повторном взятии периферии программа запаникует.
(Если всё это вас запутало, в [следующей главе] всё объясняется ещё раз, подробнее.)
-Теперь мы можем зажечь светодиод, подключённый к `row1`, `col1`, установив пин `row1` в высокий уровень (то есть включив его). Пин `col1` можно оставить в низком уровне, потому что так устроена схема матрицы светодиодов. Кроме того, `embedded-hal` спроектирован так, что любая операция с аппаратурой может вернуть ошибку, даже простое включение или выключение пина. Поскольку в нашем случае это крайне маловероятно, можно просто вызвать `unwrap()` для результата.
+Теперь мы можем зажечь светодиод, подключённый к `row1`, `col1`, установив вывод `row1` в высокий уровень (то есть включив его). Вывод `col1` можно оставить в низком уровне, потому что так устроена схема матрицы светодиодов. Кроме того, `embedded-hal` спроектирован так, что любая операция с аппаратурой может вернуть ошибку, даже простое включение или выключение вывода. Поскольку в нашем случае это крайне маловероятно, можно просто вызвать `unwrap()` для результата.
## Проверка
diff --git a/discovery-mb2/src/06-hello-world/README.md b/discovery-mb2/src/06-hello-world/README.md
index eeef252..427445f 100644
--- a/discovery-mb2/src/06-hello-world/README.md
+++ b/discovery-mb2/src/06-hello-world/README.md
@@ -2,17 +2,17 @@
В предыдущем разделе вы написали нечто вроде программы «Hello World». Но для программистов встраиваемых систем «настоящий Hello World» — это заставить светодиод (любой) включаться и выключаться раз в секунду. Такую программу обычно называют «blinky» (мигалка).
-Зачем мигалка? Потому что она показывает, что вы достаточно контролируете плату, чтобы выполнить эту простую задачу. Вы можете загрузить программу на устройство и запустить её, найти нужный пин на MCU и включить его, сделать паузу на фиксированное время. Когда контроль на таком уровне, остальные задачи становятся гораздо проще.
+Зачем мигалка? Потому что она показывает, что вы достаточно контролируете плату, чтобы выполнить эту простую задачу. Вы можете загрузить программу на устройство и запустить её, найти нужный вывод на MCU и включить его, сделать паузу на фиксированное время. Когда вы контролируете плату на таком уровне, остальные задачи становятся гораздо проще.
-В предыдущих главах вы узнали несколько способов загрузить программу на MB2. Теперь остаётся вопрос: какой пин включать и выключать и как делать паузы между этими действиями.
+В предыдущих главах вы узнали несколько способов загрузить программу на MB2. Теперь остаётся вопрос: какой вывод включать и выключать и как делать паузы между этими действиями.
-Начнём с того, как работать с нужными пинами. Есть путь, которым можно пройти, если умеете читать электрические схемы («schematic»). Найдите [схему MB2], выберите на ней светодиод, который хотите включать и выключать, и определите, к каким GPIO-пинам nRF52833 он подключён. (В этом отношении MB2 немного необычен: обычно светодиод подключён к одному пину, который его включает или выключает. Светодиодный «дисплей» MB2 устроен сложнее: он позволяет включать и выключать сразу комбинации светодиодов, и этой возможностью мы скоро воспользуемся.)
+Начнём с того, как работать с нужными выводами. Один из способов — прочитать электрическую схему («schematic»), если вы умеете это делать. Найдите [схему MB2], выберите на ней светодиод, который хотите включать и выключать, и определите, к каким GPIO-выводам nRF52833 он подключён. (В этом отношении MB2 немного необычен: обычно светодиод подключён к одному выводу, который его включает или выключает. Светодиодный «дисплей» MB2 устроен сложнее: он позволяет включать и выключать сразу комбинации светодиодов, и этой возможностью мы скоро воспользуемся.)
[схему MB2]: https://github.com/microbit-foundation/microbit-v2-hardware/blob/main/V2.21/MicroBit_V2.2.1_nRF52820%20schematic.PDF
-Мы будем работать со светодиодом в верхнем левом углу дисплея MB2. Проследив провода `ROW1` и `COL1`, к которым подключён этот светодиод, видим, что они идут к пинам nRF52833 с обозначениями `AC17`/`P0.21` и `B11`/`AIN4`/`P0.28`. Если копнуть документацию глубже, выясняется, что `AC17` и `B11` — это координаты физических выводов (точнее, шариков припоя) на нижней стороне чипа; нам они не нужны. `AIN4` означает, что этот пин может работать как «аналоговый вход» (Analog Input), но сейчас это тоже нам не важно. (Это пригодится позже.)
+Мы будем работать со светодиодом в верхнем левом углу дисплея MB2. Проследив провода `ROW1` и `COL1`, к которым подключён этот светодиод, видим, что они идут к выводам nRF52833 с обозначениями `AC17`/`P0.21` и `B11`/`AIN4`/`P0.28`. Если копнуть документацию глубже, выясняется, что `AC17` и `B11` — это координаты физических выводов (точнее, шариков припоя) на нижней стороне чипа; нам они не нужны. `AIN4` означает, что этот вывод может работать как «аналоговый вход» (Analog Input), но сейчас это тоже нам не важно. (Это пригодится позже.)
-Остаются `P0.21` и `P0.28`. Эти обозначения соответствуют битам в памяти nRF52833, которые можно включать и выключать, чтобы зажечь светодиод. Из-за законов электроники, если пин `P0.21` включён (то есть выдаёт 3,3 В), а пин `P0.28` выключен (то есть принимает напряжение), светодиод загорится.
+Остаются `P0.21` и `P0.28`. Эти обозначения соответствуют битам в памяти nRF52833, которые можно включать и выключать, чтобы зажечь светодиод. Из-за законов электроники, если вывод `P0.21` включён (то есть выдаёт 3,3 В), а вывод `P0.28` выключен (то есть принимает напряжение), светодиод загорится.
Но что делать в программе, чтобы это произошло? Будем работать на уровне крейта `nrf52833-hal`. Hardware Abstraction Layer (HAL) — это программный слой, призванный упростить работу с конкретным микроконтроллером. Как видно из названия, у нас есть HAL для микроконтроллера MB2. В нём есть всё необходимое, чтобы включить нужный светодиод.
@@ -28,4 +28,4 @@ cargo run --example light-up
{{#include examples/light-up.rs}}
```
-Обратите внимание, что к PAC этого чипа мы обращаемся через наш HAL-крейт. Чтобы получить доступ к пинам, нужна довольно сложная процедура. Наконец, поскольку можно сразу задать пинам нужные уровни при инициализации, их не нужно переключать отдельно. Переключение пинов — тема следующего раздела.
+Обратите внимание, что к PAC этого чипа мы обращаемся через наш HAL-крейт. Чтобы получить доступ к выводам, нужна довольно сложная процедура. Наконец, поскольку можно сразу задать выводам нужные уровни при инициализации, их не нужно переключать отдельно. Переключение выводов — тема следующего раздела.
diff --git a/discovery-mb2/src/06-hello-world/board-support-crate.md b/discovery-mb2/src/06-hello-world/board-support-crate.md
index 3be47e6..5d436bb 100644
--- a/discovery-mb2/src/06-hello-world/board-support-crate.md
+++ b/discovery-mb2/src/06-hello-world/board-support-crate.md
@@ -12,6 +12,6 @@
{{#include src/main.rs}}
```
-В этот раз мы изменили немного. Наш крейт поддержки платы скрыл PAC (пока что). Что важнее, он сделал это, позволив нам просто использовать понятные имена для строк и столбцов GPIO-пинов светодиода.
+В этот раз мы изменили немного. Наш крейт поддержки платы скрыл PAC (пока что). Что важнее, он сделал это, позволив нам просто использовать понятные имена для строк и столбцов GPIO-выводов светодиода.
Крейт `microbit-v2` предоставляет ещё более продвинутую поддержку для светодиодного «дисплея». Скоро мы увидим, как она используется для задач поинтереснее мигалки.
diff --git a/discovery-mb2/src/06-hello-world/portability.md b/discovery-mb2/src/06-hello-world/portability.md
index 0d422d9..8a808b0 100644
--- a/discovery-mb2/src/06-hello-world/portability.md
+++ b/discovery-mb2/src/06-hello-world/portability.md
@@ -8,7 +8,7 @@
Но у этого есть и приятный плюс: наш код становится по-настоящему переносимым. На другой плате настройка может отличаться, но сам цикл мигалки будет точно таким же!
-Посмотрим на мигалку для Sipeed Longan Nano. Это небольшая плата примерно за 5 долларов, которая, как и MB2, является встраиваемой платой с MCU. А во всём остальном она совершенно другая: другой процессор (GD32VF103 с системой команд RISC-V, совсем не похожей на Arm, которую используем мы), другая периферия, другая плата. Но к ней подключён светодиод через GPIO-пин, так что её тоже можно заставить мигать.
+Посмотрим на мигалку для Sipeed Longan Nano. Это небольшая плата примерно за 5 долларов, которая, как и MB2, является встраиваемой платой с MCU. А во всём остальном она совершенно другая: другой процессор (GD32VF103 с системой команд RISC-V, совсем не похожей на Arm, которую используем мы), другая периферия, другая плата. Но к ней подключён светодиод через GPIO-вывод, так что её тоже можно заставить мигать.
```rust
{{#include nanoblinky.rs}}
diff --git a/discovery-mb2/src/06-hello-world/toggle-it.md b/discovery-mb2/src/06-hello-world/toggle-it.md
index 3ee33f8..bb57100 100644
--- a/discovery-mb2/src/06-hello-world/toggle-it.md
+++ b/discovery-mb2/src/06-hello-world/toggle-it.md
@@ -10,6 +10,6 @@
Здесь крейт `embedded-hal` предоставляет трейты Rust, которые нужны, чтобы устанавливать и сбрасывать состояние светодиода. Благодаря этому данная часть кода переносима на любой HAL на Rust, который реализует трейты `embedded-hal`, как и наш.
-Но постойте: ни один светодиод не мигает! Второй горит чуть тусклее первого, но оба светятся ровно… или всё-таки нет? По умолчанию MB2 выполняет 64 *миллиона* инструкций в секунду. Допустим, включение или выключение светодиода «под капотом» занимает несколько десятков инструкций. (Возможно, столько в отладочной сборке, а в релизной — гораздо меньше. К тому же пинам нужно время, чтобы сменить состояние. Точно не знаю.) В любом случае второй светодиод включается и выключается сотни тысяч, а то и миллионы раз в секунду. Глаз просто не успевает за этим.
+Но постойте: ни один светодиод не мигает! Второй горит чуть тусклее первого, но оба светятся ровно… или всё-таки нет? По умолчанию MB2 выполняет 64 *миллиона* инструкций в секунду. Допустим, включение или выключение светодиода «под капотом» занимает несколько десятков инструкций. (Возможно, столько в отладочной сборке, а в релизной — гораздо меньше. К тому же выводам нужно время, чтобы сменить состояние. Точно не знаю.) В любом случае второй светодиод включается и выключается сотни тысяч, а то и миллионы раз в секунду. Глаз просто не успевает за этим.
Между переключениями нужна пауза. Оказывается, ждать — самая сложная часть.
diff --git a/discovery-mb2/src/07-led-roulette/README.md b/discovery-mb2/src/07-led-roulette/README.md
index c6c7a9f..fb7f711 100644
--- a/discovery-mb2/src/07-led-roulette/README.md
+++ b/discovery-mb2/src/07-led-roulette/README.md
@@ -6,7 +6,7 @@
-Работать с пинами светодиодов по отдельности довольно утомительно (особенно если, как здесь, нужны почти все), поэтому можно воспользоваться BSP-крейтом `microbit-v2`, о котором говорили ранее, и работать со светодиодным «дисплеем» MB2. Это выглядит так (`examples/light-it-all.rs`):
+Работать с выводами светодиодов по отдельности довольно утомительно (особенно если, как здесь, нужны почти все), поэтому можно воспользоваться BSP-крейтом `microbit-v2`, о котором говорили ранее, и работать со светодиодным «дисплеем» MB2. Это выглядит так (`examples/light-it-all.rs`):
```rust
{{#include examples/light-it-all.rs}}
diff --git a/discovery-mb2/src/07-led-roulette/my-solution.md b/discovery-mb2/src/07-led-roulette/my-solution.md
index 8233e3b..071c43d 100644
--- a/discovery-mb2/src/07-led-roulette/my-solution.md
+++ b/discovery-mb2/src/07-led-roulette/my-solution.md
@@ -52,4 +52,4 @@ Total 283715
Ваши числа могут немного отличаться в зависимости от того, как собран код: это нормально.
-Умеете читать этот вывод? Секция `text` содержит инструкции программы. Секция `rodata` содержит данные только для чтения, которые хранятся вместе с инструкциями программы. Секции `data` и `bss` содержат переменные, выделенные статически в RAM (`static`-переменные). Если вы помните характеристики микроконтроллера micro:bit, вы должны заметить, что его флеш-памяти меньше чем вдвое больше размера этого очень простого бинарника. Может ли это быть правдой? Как видно из статистики размеров, основную часть бинарника составляют отладочные секции. Однако они никогда не прошиваются в микроконтроллер: для выполнения программы они не нужны.
+Умеете читать этот вывод? Секция `text` содержит инструкции программы. Секция `rodata` содержит данные только для чтения, которые хранятся вместе с инструкциями программы. Секции `data` и `bss` содержат переменные, выделенные статически в RAM (`static`-переменные). Если вы помните характеристики micro:bit, то заметите, что его флеш-память меньше чем вдвое больше размера этого очень простого бинарника. Может ли это быть правдой? Как видно из статистики размеров, основную часть бинарника составляют отладочные секции. Однако они никогда не прошиваются в микроконтроллер: для выполнения программы они не нужны.
diff --git a/discovery-mb2/src/08-inputs-and-outputs/README.md b/discovery-mb2/src/08-inputs-and-outputs/README.md
index 0be1204..09e1ef7 100644
--- a/discovery-mb2/src/08-inputs-and-outputs/README.md
+++ b/discovery-mb2/src/08-inputs-and-outputs/README.md
@@ -1,14 +1,14 @@
# Входы и опрос
-В предыдущих главах мы в основном использовали пины GPIO как выходы: включали и выключали светодиоды. Однако пины GPIO можно настроить и как входы: тогда программа сможет считывать сигналы из внешнего мира, например нажатия кнопок или переключение тумблеров. В этой главе мы научимся считывать такие входные сигналы и делать с ними что-нибудь полезное.
+В предыдущих главах мы в основном использовали выводы GPIO как выходы: включали и выключали светодиоды. Однако выводы GPIO можно настроить и как входы: тогда программа сможет считывать сигналы из внешнего мира, например нажатия кнопок или переключение тумблеров. В этой главе мы научимся считывать такие входные сигналы и делать с ними что-нибудь полезное.
## Чтение состояния кнопок
-На micro:bit v2 есть две физические кнопки, Button A и Button B, подключённые к пинам GPIO, настроенным как входы. Точнее, Button A подключена к пину P0.14, а Button B — к пину P0.23. (Это можно проверить по официальной [таблице пинов].)
+На micro:bit v2 есть две физические кнопки, Button A и Button B, подключённые к выводам GPIO, настроенным как входы. Точнее, Button A подключена к выводу P0.14, а Button B — к выводу P0.23. (Это можно проверить по официальной [таблице выводов].)
-[таблице пинов]: https://tech.microbit.org/hardware/schematic/#v2-pinmap
+[таблице выводов]: https://tech.microbit.org/hardware/schematic/#v2-pinmap
-Чтение состояния входа GPIO сводится к проверке того, высокий ли уровень напряжения на пине (3,3 В, логическая единица) или низкий (0 В, логический ноль). Каждая кнопка micro:bit подключена к пину. Когда кнопка *не* нажата, пин удерживается в высоком уровне; когда кнопка нажата, пин удерживается в низком.
+Чтение состояния входа GPIO сводится к проверке того, высокий ли уровень напряжения на выводе (3,3 В, логическая единица) или низкий (0 В, логический ноль). Каждая кнопка micro:bit подключена к выводу. Когда кнопка *не* нажата, вывод удерживается в высоком уровне; когда кнопка нажата, вывод удерживается в низком.
Теперь применим эти знания, чтобы считать состояние Button A: проверим, находится ли она в «низком» уровне (то есть нажата).
diff --git a/discovery-mb2/src/09-registers/README.md b/discovery-mb2/src/09-registers/README.md
index 8354361..c232d43 100644
--- a/discovery-mb2/src/09-registers/README.md
+++ b/discovery-mb2/src/09-registers/README.md
@@ -18,15 +18,15 @@
Адрес `0x50000504` указывает на *регистр*. Регистр — это особая область памяти, которая управляет *периферией*. Периферия — это электронный блок, расположенный рядом с процессором внутри корпуса микроконтроллера, который добавляет процессору дополнительные возможности. Ведь сам по себе процессор умеет только считать и выполнять логические операции.
-Этот конкретный регистр управляет выводами (*пинами*) GPIO — универсального ввода-вывода (GPIO *является* периферией) — и может использоваться, чтобы *выставлять* каждый из этих пинов в *низкий* или *высокий* уровень.
+Этот конкретный регистр управляет выводами (*pins*) GPIO — универсального ввода-вывода (GPIO *является* периферией) — и может использоваться, чтобы *выставлять* каждый из этих выводов в *низкий* или *высокий* уровень.
-(В nRF52833 больше 32 GPIO, но процессор 32-битный. Поэтому пины GPIO разбиты на две группы, «P0» и «P1», с набором регистров для чтения, записи и настройки каждой группы. Адрес выше — это адрес выходного регистра для пинов P0.)
+(В nRF52833 больше 32 GPIO, но процессор 32-битный. Поэтому выводы GPIO разбиты на две группы, «P0» и «P1», с набором регистров для чтения, записи и настройки каждой группы. Адрес выше — это адрес выходного регистра для выводов P0.)
## Отступление: светодиоды, цифровые выходы и уровни напряжения
-Выставлять? Пин? Низкий? Высокий?
+Выставлять? Вывод? Низкий? Высокий?
-Пин — это электрический контакт. У нашего микроконтроллера их несколько, и некоторые из них подключены к светодиодам (Light Emitting Diode, LED). Светодиод излучает свет, когда на него подано напряжение. Как следует из названия, светодиод также работает как «диод»: он пропускает электрический ток только в одном направлении. Подключите светодиод «в прямом направлении» — и он светится. Подключите «в обратном» — ничего не произойдёт.
+Вывод — это электрический контакт. У нашего микроконтроллера их несколько, и некоторые из них подключены к светодиодам (Light Emitting Diode, LED). Светодиод излучает свет, когда на него подано напряжение. Как следует из названия, светодиод также работает как «диод»: он пропускает электрический ток только в одном направлении. Подключите светодиод «в прямом направлении» — и он светится. Подключите «в обратном» — ничего не произойдёт.
-К счастью, пины микроконтроллера подключены так, что светодиоды можно включать правильной стороной. Нужно лишь подать на пины достаточное напряжение, чтобы зажечь светодиод. Пины, к которым подключены светодиоды, обычно настраивают как *цифровые выходы*: они могут выдавать два уровня напряжения — «низкий», 0 В, или «высокий», 3 В. Высокий уровень зажигает светодиод, а низкий — гасит.
+К счастью, выводы микроконтроллера подключены так, что светодиоды можно включать правильной стороной. Нужно лишь подать на выводы достаточное напряжение, чтобы зажечь светодиод. Выводы, к которым подключены светодиоды, обычно настраивают как *цифровые выходы*: они могут выдавать два уровня напряжения — «низкий», 0 В, или «высокий», 3 В. Высокий уровень зажигает светодиод, а низкий — гасит.
-Эти состояния «низкий» и «высокий» напрямую соответствуют понятиям цифровой логики: «низкий» — это `0` или `false`, а «высокий» — `1` или `true`. Поэтому такая конфигурация пина и называется цифровым выходом.
+Эти состояния «низкий» и «высокий» напрямую соответствуют понятиям цифровой логики: «низкий» — это `0` или `false`, а «высокий» — `1` или `true`. Поэтому такая конфигурация вывода и называется цифровым выходом.
Противоположность цифровому выходу — цифровой вход. Так же как цифровой выход может быть `0` или `1`, цифровой вход тоже может быть `0` или `1`. Разница в том, что цифровые выходы *задают* напряжение, а цифровые входы *считывают* его. Когда микроконтроллер считывает уровень напряжения выше порога высокого уровня, он интерпретирует его как `1`, а когда уровень ниже порога низкого уровня — как `0`.
diff --git a/discovery-mb2/src/09-registers/rtrm.md b/discovery-mb2/src/09-registers/rtrm.md
index c1efb5c..2859e56 100644
--- a/discovery-mb2/src/09-registers/rtrm.md
+++ b/discovery-mb2/src/09-registers/rtrm.md
@@ -1,17 +1,17 @@
# RTRM: читаем справочное руководство
-Мы уже встречались с пинами GPIO на nRF52833. В этом чипе (как и во многих других) пины GPIO сгруппированы в *порты*. Есть два порта, Port 0 и Port 1, их сокращённо обозначают `P0` и `P1`. Пины внутри каждого порта нумеруются с нуля. В порту 0 есть 32 пина, от `P0.00` до `P0.31`, а в порту 1 — 10 пинов, от `P1.00` до `P1.09`.
+Мы уже встречались с выводами GPIO на nRF52833. В этом чипе (как и во многих других) выводы GPIO сгруппированы в *порты*. Есть два порта, Port 0 и Port 1, их сокращённо обозначают `P0` и `P1`. Выводы внутри каждого порта нумеруются с нуля. В порту 0 есть 32 вывода, от `P0.00` до `P0.31`, а в порту 1 — 10 выводов, от `P1.00` до `P1.09`.
-Первое, что нужно узнать, — какой пин к какому светодиоду подключён. Раньше мы делали это, прослеживая схему. Но это сложный путь: нужная информация есть в [таблице пинов] MB2.
+Первое, что нужно узнать, — какой вывод к какому светодиоду подключён. Раньше мы делали это, прослеживая схему. Но это сложный путь: нужная информация есть в [таблице выводов] MB2.
-[таблице пинов]: https://tech.microbit.org/hardware/schematic/#v2-pinmap
+[таблице выводов]: https://tech.microbit.org/hardware/schematic/#v2-pinmap
В таблице сказано:
-- `ROW1`, верхний ряд светодиодов, подключён к пину `P0.21`. `P0.21` — это сокращение от «пин 21 на порту 0».
-- `ROW5`, нижний ряд светодиодов, подключён к пину `P0.19`.
+- `ROW1`, верхний ряд светодиодов, подключён к выводу `P0.21`. `P0.21` — это сокращение от «вывод 21 на порту 0».
+- `ROW5`, нижний ряд светодиодов, подключён к выводу `P0.19`.
-До этого момента мы знаем, что нужно менять состояние пинов `P0.21` и `P0.19`, чтобы включать и выключать верхний и нижний ряды. Эти пины относятся к порту 0, поэтому для их настройки используем периферию `P0`.
+Итак, мы знаем, что нужно менять состояние выводов `P0.21` и `P0.19`, чтобы включать и выключать верхний и нижний ряды. Эти выводы относятся к порту 0, поэтому для их настройки используем периферию `P0`.
С каждой периферией связан *блок регистров*. Блок регистров — это набор регистров, расположенных в непрерывной области памяти. Адрес, с которого начинается блок регистров, называется базовым адресом. Нам нужно узнать базовый адрес периферии `P0`. Эта информация есть в следующем разделе [спецификации продукта] микроконтроллера:
@@ -31,7 +31,7 @@
Итак, `0x5000_0000` + `0x504` = `0x50000504`. Знакомый адрес! Наконец-то!
-Это тот самый регистр, в который мы писали. Документация сообщает кое-что интересное. Во-первых, в этот регистр можно и записывать, и читать из него. Во-вторых, регистр — это 32-битная область памяти, и каждый бит отражает состояние соответствующего пина: например, бит 19 соответствует пину 19. Установка бита в 1 включает выход пина, а установка в 0 — сбрасывает его. Кроме того, видно, что все выходы пинов по умолчанию отключены, так как значение всех битов после сброса — 0.
+Это тот самый регистр, в который мы писали. Документация сообщает кое-что интересное. Во-первых, в этот регистр можно и записывать, и читать из него. Во-вторых, регистр — это 32-битная область памяти, и каждый бит отражает состояние соответствующего вывода: например, бит 19 соответствует выводу 19. Установка бита в 1 включает выход соответствующего вывода, а установка в 0 — выключает его. Кроме того, видно, что по умолчанию все выходы отключены, так как значение всех битов после сброса — 0.
Мы будем использовать команду GDB `examine`: `x`. В зависимости от настроек GDB-сервера GDB может отказаться читать память, которая не описана. Это поведение можно отключить так:
diff --git a/discovery-mb2/src/09-registers/spooky-action-at-a-distance.md b/discovery-mb2/src/09-registers/spooky-action-at-a-distance.md
index 6dbf932..2e3ad8b 100644
--- a/discovery-mb2/src/09-registers/spooky-action-at-a-distance.md
+++ b/discovery-mb2/src/09-registers/spooky-action-at-a-distance.md
@@ -1,6 +1,6 @@
# Жуткое действие на расстоянии
-`OUT` — не единственный регистр, который управляет пинами порта `P0`. Регистр `OUTSET` тоже позволяет менять значения пинов, как и `OUTCLR`. Однако `OUTSET` и `OUTCLR` не позволяют узнать текущее состояние выходов порта `P0`.
+`OUT` — не единственный регистр, который управляет выводами порта `P0`. Регистр `OUTSET` тоже позволяет менять значения выводов, как и `OUTCLR`. Однако `OUTSET` и `OUTCLR` не позволяют узнать текущее состояние выходов порта `P0`.
Регистр `OUTSET` описан в [спецификации продукта]:
diff --git a/discovery-mb2/src/09-registers/src/lib.rs b/discovery-mb2/src/09-registers/src/lib.rs
index 56249bb..d474779 100644
--- a/discovery-mb2/src/09-registers/src/lib.rs
+++ b/discovery-mb2/src/09-registers/src/lib.rs
@@ -16,7 +16,7 @@ pub fn init() -> (&'static p0::RegisterBlock, &'static p1::RegisterBlock) {
rtt_target::rtt_init_print!();
let device_periphs = pac::Peripherals::take().unwrap();
- // `display_pins!` инициализирует пины дисплея как выходы в режиме push-pull
+ // `display_pins!` инициализирует выводы дисплея как выходы в режиме push-pull
let port0 = hal::gpio::p0::Parts::new(device_periphs.P0);
let port1 = hal::gpio::p1::Parts::new(device_periphs.P1);
let _display_pins = microbit::display_pins!(port0, port1);
diff --git a/discovery-mb2/src/10-serial-port/README.md b/discovery-mb2/src/10-serial-port/README.md
index 17e5daa..4f99973 100644
--- a/discovery-mb2/src/10-serial-port/README.md
+++ b/discovery-mb2/src/10-serial-port/README.md
@@ -1,6 +1,6 @@
# Последовательный порт
-Ближайший аналог универсального стандарта ввода-вывода для современных встраиваемых плат — «последовательный порт». Почти у каждого микроконтроллера есть возможность сделать несколько своих пинов последовательным портом, и почти на каждой плате с микроконтроллером эти пины легко доступны. MB2 — не исключение.
+Ближайший аналог универсального стандарта ввода-вывода для современных встраиваемых плат — «последовательный порт». Почти у каждого микроконтроллера есть возможность сделать несколько своих выводов последовательным портом, и почти на каждой плате с микроконтроллером эти выводы легко доступны. MB2 — не исключение.
В этой главе мы объясним, что вообще такое последовательный порт. Затем покажем, как настроить компьютер с «виртуальным последовательным портом» через USB и как использовать этот виртуальный порт с помощью «программы-терминала», чтобы общаться с последовательным портом MB2.
diff --git a/discovery-mb2/src/11-uart/send-a-single-byte.md b/discovery-mb2/src/11-uart/send-a-single-byte.md
index 3e5ea8b..218fdbf 100644
--- a/discovery-mb2/src/11-uart/send-a-single-byte.md
+++ b/discovery-mb2/src/11-uart/send-a-single-byte.md
@@ -21,7 +21,7 @@ uarte::Uarte::new(
);
```
-Эта функция забирает во владение представление периферии UARTE в Rust (`board.UARTE0`) и пины TX/RX платы (`board.uart.into()`), так что никто другой не может вмешаться ни в периферию UARTE, ни в наши пины, пока мы ими пользуемся. Затем конструктору передаются два параметра: скорость в бодах (с ней вы уже знакомы) и параметр «parity». Чётность (parity) — это способ, с помощью которого линии последовательной связи проверяют, не были ли данные повреждены при передаче. Здесь он нам не нужен, поэтому мы его просто исключаем. Затем результат оборачивается в тип `UartePort`, чтобы им было удобно пользоваться.
+Эта функция забирает во владение представление периферии UARTE в Rust (`board.UARTE0`) и выводы TX/RX платы (`board.uart.into()`), так что никто другой не может вмешаться ни в периферию UARTE, ни в наши выводы, пока мы ими пользуемся. Затем конструктору передаются два параметра: скорость в бодах (с ней вы уже знакомы) и параметр «parity». Чётность (parity) — это способ, с помощью которого линии последовательной связи проверяют, не были ли данные повреждены при передаче. Здесь он нам не нужен, поэтому мы его просто исключаем. Затем результат оборачивается в тип `UartePort`, чтобы им было удобно пользоваться.
После инициализации отправляем нашу `X` (ASCII-код 88) через только что созданный экземпляр UART. Эти последовательные функции «блокирующие»: они ждут, пока данные будут отправлены, и только потом возвращают управление. Это не всегда то, что нужно: пока байт уходит по проводу, микроконтроллер мог бы выполнить много работы. Но в нашем случае это удобно, да и другой работы у нас всё равно нет.
diff --git a/discovery-mb2/src/12-i2c/read-a-single-register.md b/discovery-mb2/src/12-i2c/read-a-single-register.md
index 0666f98..dde161a 100644
--- a/discovery-mb2/src/12-i2c/read-a-single-register.md
+++ b/discovery-mb2/src/12-i2c/read-a-single-register.md
@@ -19,7 +19,7 @@
{{#include examples/chip-id.rs}}
```
-Если не считать инициализации, этот код должен быть понятен, если вы разобрались в протоколе I2C, описанном выше. Инициализация работает так же, как в главе про UART. В конструктор мы передаём периферию, а также пины, которые используются для связи с чипом, а затем частоту, на которой должна работать шина, — в данном случае 100 кГц (`K100`, потому что идентификаторы в Rust не могут начинаться с цифры).
+Если не считать инициализации, этот код должен быть понятен, если вы разобрались в протоколе I2C, описанном выше. Инициализация работает так же, как в главе про UART. В конструктор мы передаём периферию, а также выводы, которые используются для связи с чипом, а затем частоту, на которой должна работать шина, — в данном случае 100 кГц (`K100`, потому что идентификаторы в Rust не могут начинаться с цифры).
[спецификацию продукта nRF52833]: https://docs-be.nordicsemi.com/bundle/ps_nrf52833/attach/nRF52833_PS_v1.7.pdf
[модуля `twi(m)`]: https://docs.rs/microbit-v2/0.11.0/microbit/hal/twim/index.html
diff --git a/discovery-mb2/src/15-interrupts/README.md b/discovery-mb2/src/15-interrupts/README.md
index bd0ecaf..8f81bdf 100644
--- a/discovery-mb2/src/15-interrupts/README.md
+++ b/discovery-mb2/src/15-interrupts/README.md
@@ -40,9 +40,9 @@ ISR «возвращает управление» с помощью специа
* Компилятор не даст вызывать ISR напрямую из обычного кода.
-Для настройки прерывания есть два шага. Сначала GPIOTE нужно настроить так, чтобы он генерировал прерывание, когда пин, подключённый к Button A, переходит из высокого уровня напряжения в низкий. Затем NVIC нужно настроить так, чтобы он разрешал это прерывание. Порядок важен: если сделать всё в «неправильном» порядке, прерывание может возникнуть раньше, чем вы будете к нему готовы.
+Для настройки прерывания есть два шага. Сначала GPIOTE нужно настроить так, чтобы он генерировал прерывание, когда вывод, подключённый к Button A, переходит из высокого уровня напряжения в низкий. Затем NVIC нужно настроить так, чтобы он разрешал это прерывание. Порядок важен: если сделать всё в «неправильном» порядке, прерывание может возникнуть раньше, чем вы будете к нему готовы.
-**Примечание.** Как и у большинства микроконтроллеров, у GPIOTE есть много гибкости в том, когда он может генерировать прерывание. Прерывания могут возникать при переходе пина от низкого к высокому, от высокого к низкому (как здесь), при любом изменении («фронт»), когда пин в низком уровне или когда в высоком. На nRF52833 прерывание генерирует событие, которое в ISR нужно сбросить вручную, иначе ISR будет вызвана повторно по тому же прерыванию. У других микроконтроллеров всё может работать немного иначе: чтобы разобраться в деталях для другой платы, читайте документацию крейта Rust и микроконтроллера.
+**Примечание.** Как и у большинства микроконтроллеров, у GPIOTE есть много гибкости в том, когда он может генерировать прерывание. Прерывания могут возникать при переходе вывода от низкого к высокому, от высокого к низкому (как здесь), при любом изменении («фронт»), когда вывод в низком уровне или когда в высоком. На nRF52833 прерывание генерирует событие, которое в ISR нужно сбросить вручную, иначе ISR будет вызвана повторно по тому же прерыванию. У других микроконтроллеров всё может работать немного иначе: чтобы разобраться в деталях для другой платы, читайте документацию крейта Rust и микроконтроллера.
Когда вы нажимаете кнопку A, вы видите сообщение «ouch», а затем панику. Почему обработчик прерывания вызывает `panic!()`? Попробуйте закомментировать вызов `panic!()` и посмотрите, что произойдёт при нажатии кнопки. Вы увидите, как сообщения «ouch» бесконечно пролетают по экрану. NVIC запоминает, когда прерывание произошло: это «событие» сохраняется, пока программа явно его не сбросит. Без `panic!()` при возврате из обработчика прерывания NVIC (в этом случае) снова разрешит прерывание, заметит, что событие прерывания всё ещё ожидает обработки, и запустит обработчик снова. Так будет продолжаться вечно: каждый раз, когда обработчик прерывания возвращает управление, его вызовут снова. Как мы скоро увидим, индикацию прерывания можно сбросить внутри обработчика с помощью метода периферии `reset_event()`.
diff --git a/discovery-mb2/src/15-interrupts/addendum-pwm.md b/discovery-mb2/src/15-interrupts/addendum-pwm.md
index b77df74..8885cc9 100644
--- a/discovery-mb2/src/15-interrupts/addendum-pwm.md
+++ b/discovery-mb2/src/15-interrupts/addendum-pwm.md
@@ -6,7 +6,7 @@
Решение предыдущего раздела написано так, что на каждый цикл выходного сигнала динамика приходится два прерывания. Это примерно тысяча прерываний в секунду. На таком процессоре, как наш nRF52833, это работает нормально.
-У nRF52833 есть встроенная периферия, которая могла бы сильно снизить частоту прерываний сирены. Блок широтно-импульсной модуляции (Pulse-Width Modulation, PWM) может, среди прочего, генерировать циклы на пине динамика с частотой, которую задаёт регистр PWM. Его можно использовать для генерации базовой квадратной волны для нашей сирены. Прерывание по-прежнему понадобилось бы каждый раз, когда мы захотим поменять частоту, но это было бы что-то вроде 10 прерываний в секунду вместо 1000.
+У nRF52833 есть встроенная периферия, которая могла бы сильно снизить частоту прерываний сирены. Блок широтно-импульсной модуляции (Pulse-Width Modulation, PWM) может, среди прочего, генерировать циклы на выводе динамика с частотой, которую задаёт регистр PWM. Его можно использовать для генерации базовой квадратной волны для нашей сирены. Прерывание по-прежнему понадобилось бы каждый раз, когда мы захотим поменять частоту, но это было бы что-то вроде 10 прерываний в секунду вместо 1000.
Я не использовал блок PWM в своём решении. Отчасти потому, что хотел сосредоточиться на прерываниях. Ещё одна важная причина: блок PWM nRF52833 довольно сложен и трудно понимаем. Заставить что-то работать простым способом в суровом окружении «голого железа» всегда привлекательно.
diff --git a/discovery-mb2/src/15-interrupts/my-solution.md b/discovery-mb2/src/15-interrupts/my-solution.md
index f458f0f..cfd3d37 100644
--- a/discovery-mb2/src/15-interrupts/my-solution.md
+++ b/discovery-mb2/src/15-interrupts/my-solution.md
@@ -1,6 +1,6 @@
# Моё решение
-Мне было немного непросто понять, как обработчику прерывания вычислить время следующего прерывания, чтобы сирена продолжала звучать. В итоге я завёл пару переменных состояния: чтобы отслеживать, включён ли пин динамика или выключен (можно было бы проверить и аппаратно), и чтобы отслеживать, на каком этапе цикла «вверх — вниз» находится сирена.
+Мне было немного непросто понять, как обработчику прерывания вычислить время следующего прерывания, чтобы сирена продолжала звучать. В итоге я завёл пару переменных состояния: чтобы отслеживать, включён ли вывод динамика или выключен (можно было бы проверить и аппаратно), и чтобы отслеживать, на каком этапе цикла «вверх — вниз» находится сирена.
Все подробности есть в моём коде (`src/main.rs`).
diff --git a/discovery-mb2/src/15-interrupts/nvic-and-interrupt-priority.md b/discovery-mb2/src/15-interrupts/nvic-and-interrupt-priority.md
index 8dc311b..cea34d9 100644
--- a/discovery-mb2/src/15-interrupts/nvic-and-interrupt-priority.md
+++ b/discovery-mb2/src/15-interrupts/nvic-and-interrupt-priority.md
@@ -4,11 +4,11 @@
### Контроллер прерываний
-Прерывания позволяют процессору реагировать на события периферии, например на изменение состояния входного пина GPIO, на завершение цикла таймера или на получение нового байта по UART. Периферия содержит схемы, которые замечают событие и сообщают о нём специальной периферии для обработки прерываний. В процессорах Arm эта периферия называется NVIC — Nested Vector Interrupt Controller.
+Прерывания позволяют процессору реагировать на события периферии, например на изменение состояния входного вывода GPIO, на завершение цикла таймера или на получение нового байта по UART. Периферия содержит схемы, которые замечают событие и сообщают о нём специальной периферии для обработки прерываний. В процессорах Arm эта периферия называется NVIC — Nested Vector Interrupt Controller.
> **ПРИМЕЧАНИЕ** В других архитектурах микроконтроллеров, например RISC-V, названия и детали, описанные здесь, будут отличаться, но базовые принципы, как правило, очень похожи.
-NVIC может получать запросы на инициирование прерываний от многих периферийных устройств. Более того, у одной периферии часто бывает несколько возможных прерываний: например, у порта GPIO — прерывание для каждого пина, а у UART — и прерывание «данные получены», и прерывание «передача завершена». Задача NVIC — расставить эти прерывания по приоритету, запомнить, какие из них ещё нужно обработать, и заставить процессор выполнить соответствующий код обработчика.
+NVIC может получать запросы на инициирование прерываний от многих периферийных устройств. Более того, у одной периферии часто бывает несколько возможных прерываний: например, у порта GPIO — прерывание для каждого вывода, а у UART — и прерывание «данные получены», и прерывание «передача завершена». Задача NVIC — расставить эти прерывания по приоритету, запомнить, какие из них ещё нужно обработать, и заставить процессор выполнить соответствующий код обработчика.
### Приоритеты прерываний
@@ -32,9 +32,9 @@ NVIC может получать запросы на инициирование
Когда мы описывали NVIC, я сказал, что он может «заставить процессор выполнить код соответствующего обработчика прерывания». Но как это на самом деле работает?
-Во-первых, процессору нужен способ узнать, какой код выполнять для каждого прерывания. На процессорах Cortex-M в этом участвует область памяти, которая называется таблицей векторов. Обычно она расположена в самом начале флеш-памяти с нашим кодом, которая перепрограммируется каждый раз, когда мы загружаем новый код в процессор, и содержит список адресов — расположений в памяти для каждой функции прерывания. Конкретная раскладка начала памяти определена Arm в [Architecture Reference Manual]; для наших целей важно, что байты с 64 по 256 содержат адреса всех 48 обработчиков прерываний для используемого нами процессора nRF, по четыре байта на адрес. У каждого прерывания есть номер от 0 до 47. Например, `TIMER0` — прерывание номер 8, поэтому байты с 96 по 100 содержат четырёхбайтовый адрес его обработчика. Когда NVIC велит процессору обработать прерывание номер 8, процессор читает адрес, сохранённый в этих байтах, и переходит к нему.
+Во-первых, процессору нужен способ узнать, какой код выполнять для каждого прерывания. На процессорах Cortex-M в этом участвует область памяти, которая называется таблицей векторов. Обычно она расположена в самом начале флеш-памяти с нашим кодом (эта память перепрограммируется при каждой загрузке нового кода) и содержит список адресов — расположений в памяти каждой функции прерывания. Конкретная раскладка начала памяти определена Arm в [Architecture Reference Manual]; для наших целей важно, что байты с 64 по 256 содержат адреса всех 48 обработчиков прерываний для используемого нами процессора nRF, по четыре байта на адрес. У каждого прерывания есть номер от 0 до 47. Например, `TIMER0` — прерывание номер 8, поэтому байты с 96 по 100 содержат четырёхбайтовый адрес его обработчика. Когда NVIC велит процессору обработать прерывание номер 8, процессор читает адрес, сохранённый в этих байтах, и переходит к нему.
-Как эта таблица векторов генерируется в нашем коде? За это отвечает крейт [`cortex-m-rt`], который делает всё необходимое. Он задаёт прерывание по умолчанию для каждой неиспользуемой позиции (поскольку каждая позиция должна быть заполнена) и позволяет нашему коду переопределить это значение, когда нам нужно указать собственный обработчик прерывания. Для этого мы используем макрос `#[interrupt]`, который требует, чтобы функция имела определённое имя, связанное с обрабатываемым прерыванием. Затем крейт `cortex-m-rt` использует свой скрипт линкера, чтобы адрес этой функции оказался в нужной части памяти.
+Как эта таблица векторов генерируется в нашем коде? За это отвечает крейт [`cortex-m-rt`], который делает всё необходимое. Он задаёт прерывание по умолчанию для каждой неиспользуемой позиции (поскольку каждая позиция должна быть заполнена) и позволяет нашему коду переопределить это значение, когда нам нужно указать собственный обработчик прерывания. Для этого мы используем макрос `#[interrupt]`, который требует, чтобы функция имела определённое имя, связанное с обрабатываемым прерыванием. Затем крейт `cortex-m-rt` использует свой скрипт компоновщика, чтобы адрес этой функции оказался в нужной части памяти.
Подробнее о том, как в Rust управляются эти обработчики прерываний, см. главы об исключениях и прерываниях во [встраиваемой книге Rust].
diff --git a/discovery-mb2/src/15-interrupts/src/main.rs b/discovery-mb2/src/15-interrupts/src/main.rs
index 2d5a2da..a328cad 100644
--- a/discovery-mb2/src/15-interrupts/src/main.rs
+++ b/discovery-mb2/src/15-interrupts/src/main.rs
@@ -33,10 +33,10 @@ type SirenTimer = timer::Timer;
struct Siren {
/// Таймер, который использует сирена.
timer: SirenTimer,
- /// Пин динамика MB2. Должен принадлежать
+ /// Вывод динамика MB2. Должен принадлежать
/// этой структуре, чтобы его мог использовать обработчик прерывания.
speaker_pin: SpeakerPin,
- /// Сейчас пин динамика в высоком или низком уровне?
+ /// Находится ли сейчас вывод динамика в высоком уровне?
pin_high: bool,
/// Время в мкс с начала текущего цикла сирены.
cur_time: u32,
@@ -72,7 +72,7 @@ impl Siren {
/// Перевести сирену к следующему изменению состояния динамика.
/// Обычно вызывается из обработчика прерывания таймера.
fn step(&mut self) {
- // Переключаем пин динамика.
+ // Переключаем вывод динамика.
if self.pin_high {
self.speaker_pin.set_low().unwrap();
self.pin_high = false;
@@ -123,10 +123,9 @@ fn TIMER0() {
fn main() -> ! {
rtt_init_print!();
let board = Board::take().unwrap();
- // Удобно использовать пин, преобразованный через `degrade()`,
- // чтобы не разбираться с типом
- // пина динамика, а не выяснять его:
- // пин хранится глобально в `SIREN`, поэтому его
+ // Удобно использовать вывод, преобразованный через `degrade()`:
+ // так не придётся выяснять точный тип вывода динамика.
+ // Вывод хранится глобально в `SIREN`, поэтому его
// размер должен быть известен.
//
// Типобезопасность при этом теряется, но вряд ли
diff --git a/discovery-mb2/src/15-interrupts/the-mb2-speaker.md b/discovery-mb2/src/15-interrupts/the-mb2-speaker.md
index 8630e59..449c462 100644
--- a/discovery-mb2/src/15-interrupts/the-mb2-speaker.md
+++ b/discovery-mb2/src/15-interrupts/the-mb2-speaker.md
@@ -2,7 +2,7 @@
На вашем MB2 есть встроенный динамик — большое чёрное квадратное устройство с надписью «SPEAKER» в центре обратной стороны платы.
-Динамик работает так: он перемещает воздух в ответ на сигнал с GPIO-пина. Когда пин динамика в высоком уровне (3,3 В), внутренняя диафрагма — «конус динамика» — выдвигается полностью наружу; когда пин в низком уровне (GND), конус втягивается полностью внутрь. Когда воздух выталкивается наружу и втягивается обратно, он проходит через маленькое прямоугольное отверстие — «порт динамика» — на боковой стороне устройства. Если делать это достаточно быстро, перепады давления создадут звук.
+Динамик работает так: он перемещает воздух в ответ на сигнал с GPIO-вывода. Когда вывод динамика в высоком уровне (3,3 В), внутренняя диафрагма — «конус динамика» — выдвигается полностью наружу; когда вывод в низком уровне (GND), конус втягивается полностью внутрь. Когда воздух выталкивается наружу и втягивается обратно, он проходит через маленькое прямоугольное отверстие — «порт динамика» — на боковой стороне устройства. Если делать это достаточно быстро, перепады давления создадут звук.
diff --git a/discovery-mb2/src/15-interrupts/waiting-to-be-interrupted.md b/discovery-mb2/src/15-interrupts/waiting-to-be-interrupted.md
index bf63c3e..c3de364 100644
--- a/discovery-mb2/src/15-interrupts/waiting-to-be-interrupted.md
+++ b/discovery-mb2/src/15-interrupts/waiting-to-be-interrupted.md
@@ -1,6 +1,6 @@
# Ожидание прерывания
-Возможно, вам было интересно, почему в основном цикле мы использовали `asm::wfi()` (wait for instruction, «ждать инструкции»), а не что-то вроде `asm::nop()`.
+Возможно, вам было интересно, почему в основном цикле мы использовали `asm::wfi()` (wait for interrupt, «ждать прерывания»), а не что-то вроде `asm::nop()`.
Как говорилось раньше, `asm::nop()` означает no-operation, «нет операции», и это инструкция, которую процессор выполняет, ничего не делая. Мы вполне могли бы использовать `asm::nop()` в основном цикле, и программа вела бы себя так же. А вот микроконтроллер вёл бы себя по-другому.
diff --git a/discovery-mb2/src/16-snake-game/controls.md b/discovery-mb2/src/16-snake-game/controls.md
index c2b7748..cca3121 100644
--- a/discovery-mb2/src/16-snake-game/controls.md
+++ b/discovery-mb2/src/16-snake-game/controls.md
@@ -22,9 +22,9 @@
{{#include src/controls/init.rs}}
```
-Периферия `GPIOTE` в nRF52 имеет 8 «каналов», каждый из которых можно подключить к пину `GPIO` и настроить на реакцию на определённые события, в том числе на нарастающий фронт (переход сигнала из низкого уровня в высокий) и на спадающий фронт (из высокого в низкий). Кнопка — это пин `GPIO`, который в ненажатом состоянии имеет высокий сигнал, а в нажатом — низкий. Поэтому нажатие кнопки — это спадающий фронт.
+Периферия `GPIOTE` в nRF52 имеет 8 «каналов», каждый из которых можно подключить к выводу `GPIO` и настроить на реакцию на определённые события, в том числе на нарастающий фронт (переход сигнала из низкого уровня в высокий) и на спадающий фронт (из высокого в низкий). Кнопка — это вывод `GPIO`, который в ненажатом состоянии имеет высокий сигнал, а в нажатом — низкий. Поэтому нажатие кнопки — это спадающий фронт.
-Обратите внимание на немного неуклюжее использование функции `init_channel()` при инициализации: она позволяет не копировать код инициализации кнопок. Типы, которые различные встраиваемые крейты для MB2 от вас скрывают, иногда немного пугают. Рекомендую однажды внимательно изучить структуру типов крейтов HAL и PAC: она немного странная и требует привыкания. В частности, обратите внимание, что каждый пин micro:bit имеет *собственный уникальный тип.* Функция `degrade()` при инициализации нужна, чтобы привести их к общему типу, который можно разумно передать в `init_channel()` и далее в `input_pin()`.
+Обратите внимание на немного неуклюжее использование функции `init_channel()` при инициализации: она позволяет не копировать код инициализации кнопок. Типы, которые различные встраиваемые крейты для MB2 от вас скрывают, иногда немного пугают. Рекомендую однажды внимательно изучить структуру типов крейтов HAL и PAC: она немного странная и требует привыкания. В частности, обратите внимание, что каждый вывод micro:bit имеет *собственный уникальный тип.* Функция `degrade()` при инициализации нужна, чтобы привести их к общему типу, который можно разумно передать в `init_channel()` и далее в `input_pin()`.
Мы подключаем `channel0` к `button_a`, а `channel1` к `button_b`. В каждом случае настраиваем кнопку на генерацию событий по спадающему фронту (`hi_to_lo`). Ссылку на нашу периферию `GPIOTE` сохраняем в Mutex `GPIO`. Затем вызываем `unmask` для прерываний `GPIOTE`, позволяя аппаратуре их передавать, и `unpend`, чтобы сбросить все прерывания в состоянии ожидания (они могли появиться до разрешения прерываний).
diff --git a/discovery-mb2/src/16-snake-game/game-logic.md b/discovery-mb2/src/16-snake-game/game-logic.md
index e46d269..fa9d397 100644
--- a/discovery-mb2/src/16-snake-game/game-logic.md
+++ b/discovery-mb2/src/16-snake-game/game-logic.md
@@ -1,6 +1,6 @@
# Игровая логика
-Первым мы построим игровую логику. Вероятно, вы знакомы с играми [«Змейка»], но если нет, суть проста: игрок направляет змейку по двумерной сетке. В каждый момент в случайной клетке сетки есть «еда», и цель игры — заставить змейку съесть как можно больше еды. Каждый раз, съедая еду, змейка становится длиннее. Игрок проигрывает, если змейка врезается в собственный хвост.
+Первым мы построим игровую логику. Вероятно, вы знакомы с игрой [«Змейка»], но если нет, суть проста: игрок направляет змейку по двумерной сетке. В каждый момент в случайной клетке сетки есть «еда», и цель игры — заставить змейку съесть как можно больше еды. Каждый раз, съедая еду, змейка становится длиннее. Игрок проигрывает, если змейка врезается в собственный хвост.
[«Змейка»]: https://en.wikipedia.org/wiki/Snake_%28video_game_genre%29
diff --git a/discovery-mb2/src/README.md b/discovery-mb2/src/README.md
index c92f429..9570e8f 100644
--- a/discovery-mb2/src/README.md
+++ b/discovery-mb2/src/README.md
@@ -34,7 +34,7 @@
- Исчерпывающий учебник по теории электрических цепей или электронике. Мы разберём лишь минимум, необходимый, чтобы понять принцип работы некоторых устройств.
-- Подробности вроде скриптов линкера и процесса загрузки. Например, мы будем использовать готовые инструменты, чтобы доставить ваш код на плату, но не станем подробно объяснять, как эти инструменты устроены.
+- Подробности вроде скриптов компоновщика и процесса загрузки. Например, мы будем использовать готовые инструменты, чтобы доставить ваш код на плату, но не станем подробно объяснять, как эти инструменты устроены.
Кроме того, я не планирую переносить материал на другие отладочные платы: книга целиком построена на отладочной плате micro:bit.
diff --git a/discovery-mb2/src/appendix/1-general-troubleshooting/README.md b/discovery-mb2/src/appendix/1-general-troubleshooting/README.md
index ee54db7..6b14265 100644
--- a/discovery-mb2/src/appendix/1-general-troubleshooting/README.md
+++ b/discovery-mb2/src/appendix/1-general-troubleshooting/README.md
@@ -65,7 +65,7 @@ $ rustup target add thumbv7em-none-eabihf
*Причина:*
-Cargo должен знать, как собрать программу и как её слинковать под требования целевого устройства. Поэтому нужно задать правильные параметры в файле `.cargo/config.toml`.
+Cargo должен знать, как собрать программу и как её скомпоновать под требования целевого устройства. Поэтому нужно задать правильные параметры в файле `.cargo/config.toml`.
*Решение:*
diff --git a/discovery-mb2/src/explore.md b/discovery-mb2/src/explore.md
index c5a42a3..bea7e01 100644
--- a/discovery-mb2/src/explore.md
+++ b/discovery-mb2/src/explore.md
@@ -10,7 +10,7 @@
## Ещё о MB2
-В ходе этой книги мы затронули большую часть аппаратного обеспечения MB2. Тем не менее несколько тем для MB2 остаётся неисследованными.
+В ходе этой книги мы затронули большую часть аппаратного обеспечения MB2. Тем не менее несколько тем, связанных с MB2, остаются неисследованными.
## Прямой доступ к памяти (DMA)
@@ -26,7 +26,7 @@
## Цифровые входы и выходы
-Мы использовали пины микроконтроллера как цифровые выходы для управления светодиодами. При создании игры «Змейка» мы также увидели, как эти пины можно настроить как цифровые входы. Как цифровые входы они могут считывать двоичное состояние переключателей (вкл/выкл) или кнопок (нажата/не нажата).
+Мы использовали выводы микроконтроллера как цифровые выходы для управления светодиодами. При создании игры «Змейка» мы также увидели, как эти выводы можно настроить как цифровые входы. Как цифровые входы они могут считывать двоичное состояние переключателей (вкл/выкл) или кнопок (нажата/не нажата).
Цифровые входы и выходы абстрагированы в [модуле `digital`] `embedded-hal`, а у [`nrf52833-hal`] для них есть реализация.
@@ -38,7 +38,7 @@
Цифровых датчиков существует очень много. Их можно читать по протоколам вроде I2C и SPI. Но есть и аналоговые датчики! Такие датчики просто выдают значение напряжения, которое они измеряют, на вход АЦП процессора.
-Периферия АЦП позволяет измерить «аналоговый» уровень напряжения — например, `1.25` В — и получить «цифровое» число — например, `24824` — которое процессор может использовать в вычислениях.
+Периферия АЦП позволяет измерить «аналоговый» уровень напряжения — например, 1,25 В — и получить «цифровое» число — например, `24824` — которое процессор может использовать в вычислениях.
Раньше в `embedded-hal` были обобщённые трейты для АЦП, но для `embedded-hal` 1.0 их убрали: см. [issue #377]. Крейт `nrf52833-hal` предоставляет удобный интерфейс к АЦП, встроенному в nRF52833.
@@ -46,7 +46,7 @@
## Цифро-аналоговые преобразователи (ЦАП, DAC)
-Как и следовало ожидать, ЦАП — это ровно обратное АЦП. Можно записать цифровое число в регистр, чтобы получить определённое напряжение на каком-нибудь аналоговом выходном пине. Если этот аналоговый выход подключён к подходящей электронике, а регистр быстро записывается правильными значениями, можно, например, воспроизводить звуки или музыку.
+Как и следовало ожидать, ЦАП — это ровно обратное АЦП. Можно записать цифровое число в регистр, чтобы получить определённое напряжение на каком-нибудь аналоговом выходе. Если этот аналоговый выход подключён к подходящей электронике, а регистр быстро записывается правильными значениями, можно, например, воспроизводить звуки или музыку.
Ни у nRF52833, ни у платы MB2 нет отдельного ЦАП. Обычно эффект ЦАП получают, выводя ШИМ и используя немного электроники на выходе (RC-фильтр), чтобы «сгладить» форму ШИМ-сигнала.
diff --git a/embedded-book/src/SUMMARY.md b/embedded-book/src/SUMMARY.md
index a0e5d9d..b843e0a 100644
--- a/embedded-book/src/SUMMARY.md
+++ b/embedded-book/src/SUMMARY.md
@@ -27,7 +27,7 @@
- [Прерывания](./start/interrupts.md)
- [Периферия](./peripherals/index.md)
- [Первая попытка на Rust](./peripherals/a-first-attempt.md)
- - [Проверка заимствований](./peripherals/borrowck.md)
+ - [Анализатор заимствований](./peripherals/borrowck.md)
- [Синглтоны](./peripherals/singletons.md)
- [Статические гарантии](./static-guarantees/index.md)
- [Программирование на typestate](./static-guarantees/typestate-programming.md)
diff --git a/embedded-book/src/appendix/glossary.md b/embedded-book/src/appendix/glossary.md
index 21290a2..d690d1d 100644
--- a/embedded-book/src/appendix/glossary.md
+++ b/embedded-book/src/appendix/glossary.md
@@ -35,7 +35,7 @@ Serial Peripheral Interface (последовательный периферий
### SVD
-System View Description — формат файла на основе XML, который описывает представление программиста о устройстве микроконтроллера. Подробнее о нём можно прочитать на [сайте документации ARM CMSIS](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html).
+System View Description — формат файла на основе XML, который описывает представление программиста об устройстве микроконтроллера. Подробнее о нём можно прочитать на [сайте документации ARM CMSIS](https://www.keil.com/pack/doc/CMSIS/SVD/html/index.html).
### UART
diff --git a/embedded-book/src/c-tips/index.md b/embedded-book/src/c-tips/index.md
index 06b197e..a51c4d6 100644
--- a/embedded-book/src/c-tips/index.md
+++ b/embedded-book/src/c-tips/index.md
@@ -14,11 +14,11 @@
### Выбор кода на этапе компиляции
-Ближайший аналог `#ifdef ... #endif` в Rust — это [функции Cargo (features)][Cargo features]. Они немного формальнее, чем препроцессор C: все возможные функции явно перечисляются для каждого крейта и могут быть только включены или выключены. Функции включаются, когда вы указываете крейт как зависимость, и они аддитивны: если какой-либо крейт в дереве зависимостей включает функцию для другого крейта, эта функция будет включена для всех пользователей этого крейта.
+Ближайший аналог `#ifdef ... #endif` в Rust — это [feature-флаги Cargo (features)][Cargo features]. Они немного формальнее, чем препроцессор C: все возможные feature явно перечисляются для каждого крейта и могут быть только включены или выключены. Feature включаются, когда вы указываете крейт как зависимость, и они аддитивны: если какой-либо крейт в дереве зависимостей включает feature другого крейта, этот feature будет включён для всех пользователей этого крейта.
[Cargo features]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
-Например, у вас может быть крейт, который предоставляет библиотеку примитивов обработки сигналов. Каждый из них может требовать дополнительного времени на компиляцию или объявлять большую таблицу констант, которой вы хотели бы избежать. Вы можете объявить функцию Cargo для каждого компонента в своём `Cargo.toml`:
+Например, у вас может быть крейт, который предоставляет библиотеку примитивов обработки сигналов. Каждый из них может требовать дополнительного времени на компиляцию или объявлять большую таблицу констант, которой вы хотели бы избежать. Вы можете объявить feature Cargo для каждого компонента в своём `Cargo.toml`:
```toml
[features]
@@ -38,7 +38,7 @@ pub mod fir;
pub mod iir;
```
-Аналогичным образом можно включать блоки кода, только если функция _не_ включена, или если включено (или не включено) любое сочетание функций.
+Аналогичным образом можно включать блоки кода, только если feature _не_ включён, или при любом сочетании включённых и выключенных feature.
Кроме того, Rust предоставляет ряд автоматически задаваемых условий, которые можно использовать, например `target_arch`, чтобы выбирать разный код в зависимости от архитектуры. Полные подробности о поддержке условной компиляции см. в главе [условная компиляция][conditional compilation] справочника Rust.
@@ -48,7 +48,7 @@ pub mod iir;
### Размеры и вычисления на этапе компиляции
-Rust поддерживает `const fn` — функции, которые гарантированно вычисляются на этапе компиляции и поэтому могут использоваться там, где требуются константы, например для размера массивов. Это можно сочетать с описанными выше функциями, например:
+Rust поддерживает `const fn` — функции, которые гарантированно вычисляются на этапе компиляции и поэтому могут использоваться там, где требуются константы, например для размера массивов. Это можно сочетать с описанными выше feature, например:
```rust
const fn array_size() -> usize {
@@ -71,7 +71,7 @@ Rust предоставляет чрезвычайно мощную [систе
В общем случае там, где вы могли бы использовать макрос препроцессора C, стоит проверить, справится ли с задачей макрос по примеру. Такие макросы можно определить в своём крейте, легко использовать внутри собственного крейта или экспортировать для других пользователей. Имейте в виду, что, поскольку они должны раскрываться в целые выражения, операторы, элементы или шаблоны, некоторые сценарии использования макросов препроцессора C не будут работать; например, макрос, который раскрывается в часть имени переменной, или неполный набор элементов в списке.
-Как и в случае с функциями Cargo, стоит подумать, нужен ли вам вообще макрос. Во многих случаях обычная функция проще для понимания и будет встроена (inlined) в тот же код, что и макрос. Атрибуты [`#[inline]` и `#[inline(always)]`][attributes] дают дополнительный контроль над этим процессом, но и здесь нужна осторожность: компилятор автоматически встраивает функции из того же крейта там, где это уместно, поэтому принудительное встраивание не к месту может привести к снижению производительности.
+Как и в случае с feature-флагами Cargo, стоит подумать, нужен ли вам вообще макрос. Во многих случаях обычная функция проще для понимания и будет встроена (inlined) в тот же код, что и макрос. Атрибуты [`#[inline]` и `#[inline(always)]`][attributes] дают дополнительный контроль над этим процессом, но и здесь нужна осторожность: компилятор автоматически встраивает функции из того же крейта там, где это уместно, поэтому принудительное встраивание не к месту может привести к снижению производительности.
[attributes]: https://doc.rust-lang.org/reference/attributes.html#inline-attribute
@@ -86,9 +86,9 @@ Rust предоставляет чрезвычайно мощную [систе
Типичные сценарии использования скриптов сборки:
* предоставление информации, известной на этапе сборки, например статическое встраивание даты сборки или хеша коммита Git в исполняемый файл;
-* генерация скриптов компоновщика на этапе сборки в зависимости от выбранных функций или другой логики;
+* генерация скриптов компоновщика на этапе сборки в зависимости от выбранных feature-флагов или другой логики;
* изменение конфигурации сборки Cargo;
-* добавление дополнительных статических библиотек для линковки.
+* добавление дополнительных статических библиотек для компоновки.
На данный момент постсборочные скрипты не поддерживаются — то есть те, которые традиционно использовались для таких задач, как автоматическое создание бинарных файлов из объектных файлов сборки или вывод информации о сборке.
@@ -96,7 +96,7 @@ Rust предоставляет чрезвычайно мощную [систе
Использование Cargo в качестве системы сборки также упрощает кросс-компиляцию. В большинстве случаев достаточно указать Cargo `--target thumbv6m-none-eabi` и найти подходящий исполняемый файл в `target/thumbv6m-none-eabi/debug/myapp`.
-Для платформ, которые Rust не поддерживает нативно, вам самостоятельно понадобится собрать `libcore` для этого таргета. Для таких платформ можно использовать [Xargo] как замену Cargo, которая автоматически собирает `libcore` за вас.
+Для платформ, которые Rust не поддерживает нативно, вам самостоятельно понадобится собрать `libcore` для этой целевой платформы. Для таких платформ можно использовать [Xargo] как замену Cargo, которая автоматически собирает `libcore` за вас.
[Xargo]: https://github.com/japaric/xargo
diff --git a/embedded-book/src/collections/index.md b/embedded-book/src/collections/index.md
index 7de47be..3743b7b 100644
--- a/embedded-book/src/collections/index.md
+++ b/embedded-book/src/collections/index.md
@@ -30,7 +30,7 @@ use alloc::vec::Vec;
[`GlobalAlloc`]: https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html
-Для полноты и чтобы сделать этот раздел максимально самодостаточным, мы реализуем простой аллокатор bump pointer и используем его в качестве глобального аллокатора. Однако мы *настоятельно* советуем использовать в вашей программе проверенный временем аллокатор с crates.io вместо этого.
+Для полноты и чтобы сделать этот раздел максимально самодостаточным, мы реализуем простой аллокатор bump pointer и используем его в качестве глобального аллокатора. Однако мы *настоятельно* советуем использовать в вашей программе проверенный временем аллокатор с crates.io вместо него.
``` rust,ignore
// Реализация аллокатора bump pointer
@@ -118,7 +118,7 @@ fn main() -> ! {
}
```
-Если вы использовали коллекции из крейта `std`, эти будут знакомы, так как реализация точно такая же.
+Если вы использовали коллекции из крейта `std`, они покажутся знакомыми, так как реализация точно такая же.
## Использование `heapless`
@@ -151,7 +151,7 @@ fn main() -> ! {
## Компромиссы
-Имейте это в виду при выборе между коллекциями с выделением в куче, которые могут перемещаться, и коллекциями фиксированной ёмкости.
+Имейте это в виду при выборе между коллекциями с выделением в куче, буфер которых может перемещаться при росте, и коллекциями фиксированной ёмкости.
### Нехватка памяти и обработка ошибок
diff --git a/embedded-book/src/concurrency/index.md b/embedded-book/src/concurrency/index.md
index f2538f5..c464490 100644
--- a/embedded-book/src/concurrency/index.md
+++ b/embedded-book/src/concurrency/index.md
@@ -28,13 +28,13 @@ fn main() {
## Глобальные изменяемые данные
-В отличие от не встраиваемого Rust, обычно у нас нет роскоши создавать выделения в куче и передавать ссылки на эти данные во вновь созданный поток. Вместо этого наши обработчики прерываний могут быть вызваны в любой момент и должны знать, как обращаться к любой общей памяти, которую мы используем. На самом низком уровне это означает, что нам нужна _статически выделенная_ изменяемая память, на которую могут ссылаться и обработчик прерывания, и основной код.
+В отличие от не встраиваемого Rust, обычно у нас нет роскоши выделять память в куче и передавать ссылки на эти данные во вновь созданный поток. Вместо этого наши обработчики прерываний могут быть вызваны в любой момент и должны знать, как обращаться к любой общей памяти, которую мы используем. На самом низком уровне это означает, что нам нужна _статически выделенная_ изменяемая память, на которую могут ссылаться и обработчик прерывания, и основной код.
В Rust такие переменные [`static mut`] всегда небезопасно читать или записывать, потому что без особых мер предосторожности вы можете спровоцировать состояние гонки, при котором ваш доступ к переменной прерывается на полпути другим прерыванием, которое также обращается к этой переменной.
[`static mut`]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#accessing-or-modifying-a-mutable-static-variable
-Чтобы увидеть, как такое поведение может привести к тонким ошибкам в коде, рассмотрим встраиваемую программу, которая считает фронты входного сигнала в каждом односекундном периоде (частотомер):
+Чтобы увидеть, как такое поведение может привести к тонким ошибкам в коде, рассмотрим встраиваемую программу, которая считает фронты входного сигнала в каждом односекундном периоде (частотомер):
```rust,ignore
static mut COUNTER: u32 = 0;
@@ -223,7 +223,7 @@ fn timer() {
Мы создали полезную абстракцию, специфичную для нашей задачи со счётчиком, но для конкурентности существует много распространённых абстракций.
-Один из таких _примитивов синхронизации_ — мьютекс, сокращение от mutual exclusion (взаимное исключение). Эти конструкции обеспечивают эксклюзивный доступ к переменной, например к нашему счётчику. Поток может попытаться _заблокировать_ (или _захватить_) мьютекс, и либо немедленно преуспевает, либо блокируется в ожидании захвата блокировки, либо получает ошибку, что мьютекс не удалось заблокировать. Пока поток удерживает блокировку, ему предоставляется доступ к защищённым данным. Когда поток закончил работу, он _разблокирует_ (или _освобождает_) мьютекс, позволяя другому потоку его заблокировать. В Rust разблокировку обычно реализуют с помощью трейта [`Drop`], чтобы гарантировать, что она всегда выполняется, когда мьютекс выходит из области видимости.
+Один из таких _примитивов синхронизации_ — мьютекс, сокращение от mutual exclusion (взаимное исключение). Эти конструкции обеспечивают эксклюзивный доступ к переменной, например к нашему счётчику. Поток может попытаться _заблокировать_ (или _захватить_) мьютекс, и либо сразу успешно захватывает его, либо блокируется в ожидании захвата, либо получает ошибку о том, что мьютекс заблокировать не удалось. Пока поток удерживает блокировку, ему предоставляется доступ к защищённым данным. Когда поток закончил работу, он _разблокирует_ (или _освобождает_) мьютекс, позволяя другому потоку его заблокировать. В Rust разблокировку обычно реализуют с помощью трейта [`Drop`], чтобы гарантировать, что она всегда выполняется, когда мьютекс выходит из области видимости.
[`Drop`]: https://doc.rust-lang.org/core/ops/trait.Drop.html
diff --git a/embedded-book/src/design-patterns/hal/predictability.md b/embedded-book/src/design-patterns/hal/predictability.md
index 03f5f4c..f3baee8 100644
--- a/embedded-book/src/design-patterns/hal/predictability.md
+++ b/embedded-book/src/design-patterns/hal/predictability.md
@@ -13,5 +13,5 @@
Компилятор Rust по умолчанию не выполняет полную инлайнизацию через границы крейтов. Поскольку встраиваемые приложения чувствительны к неожиданному росту размера кода, `#[inline]` следует использовать, чтобы направлять компилятор следующим образом:
-* Все «маленькие» функции следует помечать `#[inline]`. Что считать «маленькой» функцией, — вопрос субъективный, но, как правило, к маленьким относятся все функции, которые, как ожидается, компилируются в последовательности из одной или нескольких инструкций.
+* Все «маленькие» функции следует помечать `#[inline]`. Что считать «маленькой» функцией — вопрос субъективный, но, как правило, к маленьким относятся все функции, которые, как ожидается, компилируются в последовательности из одной или нескольких инструкций.
* Функции, которые с большой вероятностью получат константные значения в качестве параметров, следует помечать как `#[inline]`. Это позволяет компилятору вычислить даже сложную логику инициализации на этапе компиляции, если входные данные функции известны.
diff --git a/embedded-book/src/interoperability/c-with-rust.md b/embedded-book/src/interoperability/c-with-rust.md
index b894073..5d5dbc8 100644
--- a/embedded-book/src/interoperability/c-with-rust.md
+++ b/embedded-book/src/interoperability/c-with-rust.md
@@ -94,9 +94,9 @@ extern "C" { pub fn cool_function( ... ); }
Поскольку компилятор Rust не умеет напрямую компилировать код на C или C++ (как и код на любом другом языке, предоставляющем интерфейс C), код не на Rust нужно скомпилировать заранее.
-Для встраиваемых проектов это чаще всего означает компиляцию кода на C/C++ в статический архив (например, `cool-library.a`), который затем объединяется с кодом на Rust на финальном шаге линковки.
+Для встраиваемых проектов это чаще всего означает компиляцию кода на C/C++ в статический архив (например, `cool-library.a`), который затем объединяется с кодом на Rust на финальном шаге компоновки.
-Если библиотека, которую вы хотите использовать, уже распространяется как статический архив, перекомпилировать код не нужно. Достаточно перевести заголовочный файл интерфейса, как описано выше, и подключить статический архив на этапе компиляции или линковки.
+Если библиотека, которую вы хотите использовать, уже распространяется как статический архив, перекомпилировать код не нужно. Достаточно перевести заголовочный файл интерфейса, как описано выше, и подключить статический архив на этапе компиляции или компоновки.
Если ваш код существует как исходный проект, нужно скомпилировать код на C/C++ в статическую библиотеку: либо запустив вашу существующую систему сборки (например, `make`, `CMake` и т. д.), либо перенеся необходимые шаги компиляции на инструмент, называемый крейтом `cc`. Для обоих этих способов нужен скрипт `build.rs`.
diff --git a/embedded-book/src/interoperability/index.md b/embedded-book/src/interoperability/index.md
index de0c8a8..d9924cc 100644
--- a/embedded-book/src/interoperability/index.md
+++ b/embedded-book/src/interoperability/index.md
@@ -32,7 +32,7 @@ fn foo(num: u32) {
Примеры и варианты использования для этого мы собираем в нашем трекере задач в [issue #61].
-[issue #61]: https://github.com/r007/EmbeddedRust-Rus/issues/61
+[issue #61]: https://github.com/rust-embedded/book/issues/61
## Взаимодействие с RTOS
@@ -44,4 +44,4 @@ fn foo(num: u32) {
Примеры и варианты использования для этого мы собираем в нашем трекере задач в [issue #62].
-[issue #62]: https://github.com/r007/EmbeddedRust-Rus/issues/62
+[issue #62]: https://github.com/rust-embedded/book/issues/62
diff --git a/embedded-book/src/interoperability/rust-with-c.md b/embedded-book/src/interoperability/rust-with-c.md
index 83eebab..2befb68 100644
--- a/embedded-book/src/interoperability/rust-with-c.md
+++ b/embedded-book/src/interoperability/rust-with-c.md
@@ -11,7 +11,7 @@
Создайте новый проект `cargo`, как обычно.
-Есть флаги, которые указывают `cargo` выпускать системную библиотеку вместо обычного таргета Rust. Это также позволяет задать для вашей библиотеки имя вывода, отличное от остальной части крейта, если вы этого хотите.
+Есть флаги, которые указывают `cargo` выпускать системную библиотеку вместо обычной библиотеки Rust. Это также позволяет задать для вашей библиотеки имя вывода, отличное от остальной части крейта, если вы этого хотите.
```toml
[lib]
@@ -26,7 +26,7 @@ crate-type = ["cdylib"] # Создаёт динамическую библ
### `#[no_mangle]`
-Компилятор Rust искажает (mangle) имена символов иначе, чем ожидают нативные линкеры. Поэтому любой функции, которую Rust экспортирует для использования за пределами Rust, нужно сообщить, что её не следует искажать.
+Компилятор Rust искажает (mangle) имена символов иначе, чем ожидают нативные компоновщики. Поэтому любой функции, которую Rust экспортирует для использования за пределами Rust, нужно сообщить, что её не следует искажать.
### `extern "C"`
@@ -47,7 +47,7 @@ pub extern "C" fn rust_function() {
Точно так же, как при использовании кода `C` в вашем проекте на Rust, вам нужно преобразовывать данные в форму, которую будет понимать остальная часть приложения, и обратно.
-## Линковка и общий контекст проекта
+## Компоновка и общий контекст проекта
Итак, одна половина задачи решена. Как теперь это использовать?
diff --git a/embedded-book/src/intro/hardware.md b/embedded-book/src/intro/hardware.md
index 54c90b2..7b5ae45 100644
--- a/embedded-book/src/intro/hardware.md
+++ b/embedded-book/src/intro/hardware.md
@@ -19,7 +19,7 @@
- Множество встроенной периферии, например таймеры, I2C, SPI и USART.
- - Контакты GPIO (универсальный ввод-вывод) и другие типы выводов, доступные через два ряда разъёмов вдоль платы.
+ - Выводы GPIO (универсальный ввод-вывод) и другие типы выводов, доступные через два ряда разъёмов вдоль платы.
- Интерфейс Mini-USB, доступный через порт с надписью «USB USER».
diff --git a/embedded-book/src/intro/index.md b/embedded-book/src/intro/index.md
index 6f9b87c..3c61900 100644
--- a/embedded-book/src/intro/index.md
+++ b/embedded-book/src/intro/index.md
@@ -19,7 +19,7 @@ Embedded Rust предназначен для всех, кто хочет зан
Эта книга старается быть максимально общей, но чтобы облегчить жизнь и читателям, и авторам, все примеры в ней используют архитектуру ARM Cortex-M. При этом книга не предполагает, что читатель знаком с этой архитектурой, и там, где это нужно, объясняет её особенности.
## Для кого эта книга
-Книга рассчитана на тех, у кого есть либо опыт во встраиваемых системах, либо опыт работы с Rust. Однако мы уверены, что любой, кому интересно встраиваемое программирование на Rust, сможет извлечь из неё пользу. Если у вас нет предварительных знаний, мы советуем прочитать раздел «Assumptions and Prerequisites» (предположения и предварительные требования) и восполнить недостающие знания, чтобы получить больше от книги и улучшить восприятие материала. В разделе «Other Resources» (другие ресурсы) вы найдёте материалы по темам, которые могут вам понадобиться.
+Книга рассчитана на тех, у кого есть либо опыт во встраиваемых системах, либо опыт работы с Rust. Однако мы уверены, что любой, кому интересно встраиваемое программирование на Rust, сможет извлечь из неё пользу. Если у вас нет предварительных знаний, мы советуем прочитать раздел «Предположения и предварительные требования» и восполнить недостающие знания, чтобы лучше усвоить материал книги. В разделе «Другие ресурсы» вы найдёте материалы по темам, которые могут вам понадобиться.
### Предположения и предварительные требования
diff --git a/embedded-book/src/intro/install.md b/embedded-book/src/intro/install.md
index 6d09ac5..9b40cb2 100644
--- a/embedded-book/src/intro/install.md
+++ b/embedded-book/src/intro/install.md
@@ -13,7 +13,7 @@ $ rustc -V
rustc 1.31.1 (b6c32da9b 2018-12-18)
```
-Для экономии трафика и места на диске стандартная установка поддерживает только нативную компиляцию. Чтобы добавить поддержку кросс-компиляции для архитектур ARM Cortex-M, выберите один из следующих таргетов (compilation targets). Для платы STM32F3DISCOVERY, которую мы используем в примерах этой книги, нужен таргет `thumbv7em-none-eabihf`.
+Для экономии трафика и места на диске стандартная установка поддерживает только нативную компиляцию. Чтобы добавить поддержку кросс-компиляции для архитектур ARM Cortex-M, выберите одну из следующих целевых платформ (compilation targets). Для платы STM32F3DISCOVERY, которую мы используем в примерах этой книги, нужна платформа `thumbv7em-none-eabihf`.
[Выберите подходящий для вас Cortex-M.](https://developer.arm.com/ip-products/processors/cortex-m#c-7d3b69ce-5b17-4c9e-8f06-59b605713133)
Cortex-M0, M0+ и M1 (архитектура ARMv6-M):
diff --git a/embedded-book/src/intro/no-std.md b/embedded-book/src/intro/no-std.md
index 46a6be6..63840bd 100644
--- a/embedded-book/src/intro/no-std.md
+++ b/embedded-book/src/intro/no-std.md
@@ -8,7 +8,7 @@
Такие среды близки к обычному ПК. Это значит, что вам предоставляется системный интерфейс [например, POSIX](https://en.wikipedia.org/wiki/POSIX), который даёт примитивы для взаимодействия с различными системами: файловыми системами, сетью, управлением памятью, потоками и т. д. Стандартные библиотеки, в свою очередь, обычно опираются на эти примитивы для реализации своей функциональности. Также у вас может быть какой-то sysroot и ограничения на использование ОЗУ и ПЗУ, а возможно, и специфическое оборудование или входы/выходы. В целом это ощущается как разработка для специализированного ПК.
## Bare-metal среды
-В bare-metal среде никакой код до запуска вашей программы не загружен. Без программного обеспечения, которое предоставляет ОС, мы не можем загрузить стандартную библиотеку. Вместо этого программа вместе с крейтами, которые она использует, может работать только с аппаратным обеспечением (bare metal). Чтобы компилятор Rust не подключал стандартную библиотеку, используйте `no_std`.
+В bare-metal среде перед запуском вашей программы не загружается никакой код. Без программного обеспечения, которое предоставляет ОС, мы не можем загрузить стандартную библиотеку. Вместо этого программа вместе с крейтами, которые она использует, может работать только с аппаратным обеспечением (bare metal). Чтобы компилятор Rust не подключал стандартную библиотеку, используйте `no_std`.
Платформонезависимые части стандартной библиотеки доступны через [libcore](https://doc.rust-lang.org/core/). libcore также исключает то, что не всегда желательно во встраиваемой среде. Одна из таких вещей — аллокатор памяти для динамического выделения памяти. Если вам нужны он или любая другая функциональность, часто существуют крейты, которые её предоставляют.
### Рантайм libstd
diff --git a/embedded-book/src/intro/tooling.md b/embedded-book/src/intro/tooling.md
index 9b1aaca..a2dcc19 100644
--- a/embedded-book/src/intro/tooling.md
+++ b/embedded-book/src/intro/tooling.md
@@ -1,6 +1,6 @@
# Инструменты
-Работа с микроконтроллерами требует использования нескольких различных инструментов, поскольку мы будем работать с архитектурой, отличной от архитектуры вашего ноутбука, и запускать и отлаживать программы на *удалённом* устройстве.
+Для работы с микроконтроллерами нужно несколько разных инструментов: мы будем работать с архитектурой, отличной от архитектуры вашего ноутбука, а запускать и отлаживать программы придётся на *удалённом* устройстве.
Мы будем использовать все перечисленные ниже инструменты. Если минимальная версия не указана, подойдёт любая свежая версия, но мы перечислили версии, которые тестировали.
diff --git a/embedded-book/src/peripherals/a-first-attempt.md b/embedded-book/src/peripherals/a-first-attempt.md
index e5a862c..d08dc17 100644
--- a/embedded-book/src/peripherals/a-first-attempt.md
+++ b/embedded-book/src/peripherals/a-first-attempt.md
@@ -27,7 +27,7 @@ struct SysTick {
}
```
-Квалификатор `#[repr(C)]` говорит компилятору Rust расположить эту структуру в памяти так же, как это делает компилятор C. Это очень важно, так как Rust позволяет переупорядочивать поля структуры, а C — нет. Представьте, сколько отладки потребовалось бы, если бы компилятор молча переставлял эти поля! С этим квалификатором у нас есть четыре 32-битных поля, которые соответствуют таблице выше. Но сама по себе эта `struct` бесполезна — нужна переменная.
+Атрибут `#[repr(C)]` говорит компилятору Rust расположить эту структуру в памяти так же, как это делает компилятор C. Это очень важно, так как Rust позволяет переупорядочивать поля структуры, а C — нет. Представьте, сколько отладки потребовалось бы, если бы компилятор молча переставлял эти поля! С этим атрибутом у нас есть четыре 32-битных поля, которые соответствуют таблице выше. Но сама по себе эта `struct` бесполезна — нужна переменная.
```rust,ignore
let systick = 0xE000_E010 as *mut SysTick;
@@ -135,4 +135,4 @@ fn thread2() {
}
```
-Аргумент `&mut self` функции `set_reload` проверяет, что на *эту конкретную* структуру `SystemTimer` нет других ссылок, но они не мешают пользователю создать вторую `SystemTimer`, которая указывает на ту же самую периферию! Код, написанный таким образом, будет работать, если автор достаточно внимателен, чтобы заметить все такие «дублирующиеся» экземпляры драйвера. Но как только код распределяется по нескольким модулям, драйверам, разработчикам и дням, такие ошибки совершать всё легче и легче.
+Аргумент `&mut self` функции `set_reload` проверяет, что на *эту конкретную* структуру `SystemTimer` нет других ссылок, но они не мешают пользователю создать вторую `SystemTimer`, которая указывает на ту же самую периферию! Код, написанный таким образом, будет работать, если автор достаточно внимателен, чтобы заметить все такие «дублирующиеся» экземпляры драйвера. Но как только код распределяется по нескольким модулям, драйверам, разработчикам и дням, такие ошибки становится всё легче допустить.
diff --git a/embedded-book/src/peripherals/borrowck.md b/embedded-book/src/peripherals/borrowck.md
index 12d3ce8..65af2ef 100644
--- a/embedded-book/src/peripherals/borrowck.md
+++ b/embedded-book/src/peripherals/borrowck.md
@@ -10,10 +10,10 @@
2. В программе мы должны иметь возможность разделять любое количество доступов только для чтения к этой периферии.
3. Если какой-то части программы нужен доступ на чтение и запись к периферии, она должна владеть единственной ссылкой на эту периферию.
-## Проверка заимствований (borrow checker)
+## Анализатор заимствований (borrow checker)
-Последние два из этих правил звучат подозрительно похоже на то, что уже делает borrow checker!
+Последние два из этих правил звучат подозрительно похоже на то, что уже делает анализатор заимствований!
Представьте, что мы могли бы передавать владение этой периферией или предоставлять неизменяемые или изменяемые ссылки на неё?
-Что ж, мы можем, но borrow checker требует, чтобы существовал ровно один экземпляр каждой периферии, чтобы Rust мог корректно с этим работать. К счастью, в аппаратуре действительно есть только один экземпляр любой данной периферии, но как отразить это в структуре нашего кода?
+Что ж, мы можем, но анализатор заимствований требует, чтобы существовал ровно один экземпляр каждой периферии, чтобы Rust мог корректно с этим работать. К счастью, в аппаратуре действительно есть только один экземпляр любой данной периферии, но как отразить это в структуре нашего кода?
diff --git a/embedded-book/src/peripherals/index.md b/embedded-book/src/peripherals/index.md
index a6646f2..879bbb1 100644
--- a/embedded-book/src/peripherals/index.md
+++ b/embedded-book/src/peripherals/index.md
@@ -4,9 +4,9 @@
У большинства микроконтроллеров есть не только ЦПУ, ОЗУ или флеш-память. Они содержат участки кремния, которые используются для взаимодействия с системами за пределами микроконтроллера, а также для прямого и косвенного взаимодействия с окружающим миром через датчики, контроллеры моторов или пользовательские интерфейсы, такие как дисплей или клавиатура. Эти компоненты в совокупности называются периферией.
-Периферия полезна тем, что позволяет разработчику переложить часть обработки на неё и не делать всё программно. Так же, как настольный разработчик переносит обработку графики на видеокарту, встраиваемый разработчик может переложить некоторые задачи на периферию, позволяя ЦПУ заниматься чем-то другим важным или ничего не делать, чтобы сэкономить энергию.
+Периферия полезна тем, что позволяет разработчику переложить часть обработки на неё и не делать всё программно. Так же, как настольный разработчик переносит обработку графики на видеокарту, встраиваемый разработчик может переложить некоторые задачи на периферию, позволяя ЦПУ заниматься другими важными делами или вообще ничего не делать, чтобы сэкономить энергию.
-Если посмотреть на основную плату старого домашнего компьютера 1970-х или 1980-х годов (да и настольные ПК сегодня не так уж далеко ушли от встраиваемых систем сегодняшнего дня), там можно увидеть:
+Если посмотреть на основную плату старого домашнего компьютера 1970-х или 1980-х годов (да и настольные ПК недавнего прошлого не так уж далеки от сегодняшних встраиваемых систем), там можно увидеть:
* процессор;
* микросхему ОЗУ;
diff --git a/embedded-book/src/peripherals/singletons.md b/embedded-book/src/peripherals/singletons.md
index 613b43b..15c80aa 100644
--- a/embedded-book/src/peripherals/singletons.md
+++ b/embedded-book/src/peripherals/singletons.md
@@ -21,7 +21,7 @@ fn main() {
}
```
-Но у этого есть несколько проблем. Это изменяемая глобальная переменная, а в Rust работа с такими переменными всегда небезопасна. К тому же эти переменные видны во всей программе, поэтому borrow checker не может помочь отслеживать ссылки и владение ими.
+Но у этого есть несколько проблем. Это изменяемая глобальная переменная, а в Rust работа с такими переменными всегда небезопасна. К тому же эти переменные видны во всей программе, поэтому анализатор заимствований не может помочь отслеживать ссылки и владение ими.
## Как это сделать в Rust?
@@ -54,7 +54,7 @@ fn main() {
Хотя работа с этой структурой — `unsafe`, после того как у нас есть содержащийся в ней `SerialPort`, нам больше не нужен ни `unsafe`, ни сама структура `PERIPHERALS`.
-У этого есть небольшие накладные расходы во время выполнения: нам нужно обернуть `SerialPort` в option и один раз вызвать `take_serial()`. Однако эта небольшая стоимость в начале позволяет использовать borrow checker во всей остальной программе.
+У этого есть небольшие накладные расходы во время выполнения: нам нужно обернуть `SerialPort` в option и один раз вызвать `take_serial()`. Однако эта небольшая стоимость в начале позволяет использовать анализатор заимствований во всей остальной программе.
## Поддержка в существующих библиотеках
@@ -114,7 +114,7 @@ impl SerialPort {
* Поскольку мы используем синглтон, есть только один способ или одно место, чтобы получить структуру `SerialPort`;
* Чтобы вызвать метод `read_speed()`, нам нужно иметь владение структурой `SerialPort` или ссылку на неё.
-Вместе эти два фактора означают, что доступ к аппаратуре возможен только тогда, когда мы надлежащим образом удовлетворили borrow checker, то есть ни в какой момент у нас не может быть нескольких изменяемых ссылок на одну и ту же аппаратуру!
+Вместе эти два фактора означают, что доступ к аппаратуре возможен только тогда, когда мы надлежащим образом удовлетворили анализатор заимствований, то есть ни в какой момент у нас не может быть нескольких изменяемых ссылок на одну и ту же аппаратуру!
```rust,ignore
fn main() {
@@ -130,9 +130,7 @@ fn main() {
## Относитесь к аппаратуре как к данным
-Кроме того, поскольку одни ссылки изменяемые, а другие — неизменяемые, становится возможным видеть, может ли функция или метод потенциально изменить состояние аппаратуры. Например,
-
-Это разрешено менять настройки аппаратуры:
+Кроме того, поскольку одни ссылки изменяемые, а другие — неизменяемые, становится возможным видеть, может ли функция или метод потенциально изменить состояние аппаратуры. Например, этой функции разрешено менять настройки аппаратуры:
```rust,ignore
fn setup_spi_port(
@@ -143,7 +141,7 @@ fn setup_spi_port(
}
```
-А это — нет:
+А этой — нет:
```rust,ignore
fn read_button(gpio: &GpioPin) -> bool {
diff --git a/embedded-book/src/portability/index.md b/embedded-book/src/portability/index.md
index 9e3953e..8fbccc5 100644
--- a/embedded-book/src/portability/index.md
+++ b/embedded-book/src/portability/index.md
@@ -2,7 +2,7 @@
Во встраиваемых системах переносимость — очень важная тема: каждый производитель и даже каждое семейство одного производителя предлагают разную периферию и возможности, и способы взаимодействия с периферией тоже различаются.
-Распространённый способ сгладить эти различия — ввести слой, который называется слоем аппаратной абстракции, или **HAL**.
+Распространённый способ сгладить эти различия — ввести слой аппаратной абстракции, или **HAL** (Hardware Abstraction Layer).
> Аппаратные абстракции — это наборы программных подпрограмм, которые эмулируют некоторые детали, специфичные для платформы, давая программам прямой доступ к аппаратным ресурсам.
>
diff --git a/embedded-book/src/start/exceptions.md b/embedded-book/src/start/exceptions.md
index bc87de3..22df2d2 100644
--- a/embedded-book/src/start/exceptions.md
+++ b/embedded-book/src/start/exceptions.md
@@ -44,7 +44,7 @@ fn SysTick() {
Вот пример, который использует системный таймер, чтобы примерно раз в секунду вызывать исключение `SysTick`. Обработчик исключения `SysTick` подсчитывает, сколько раз он был вызван, в переменной `COUNT`, а затем выводит значение `COUNT` в консоль хоста с помощью semihosting.
-> **ПРИМЕЧАНИЕ**: Вы можете запустить этот пример на любом устройстве Cortex-M; также его можно запустить на QEMU.
+> **ПРИМЕЧАНИЕ**: вы можете запустить этот пример на любом устройстве Cortex-M; также его можно запустить на QEMU.
```rust,ignore
#![deny(unsafe_code)]
@@ -133,7 +133,7 @@ fn DefaultHandler() {
}
```
-Эта функция предоставляется крейтом `cortex-m-rt`, помечена как `#[no_mangle]`, поэтому на "DefaultHandler" можно поставить точку останова и перехватывать *необработанные* исключения.
+Эта функция предоставляется крейтом `cortex-m-rt` и помечена как `#[no_mangle]`, поэтому на `DefaultHandler` можно поставить точку останова и перехватывать *необработанные* исключения.
`DefaultHandler` можно переопределить с помощью атрибута `exception`:
@@ -154,7 +154,7 @@ fn DefaultHandler(irqn: i16) {
Вот пример, который выполняет недопустимую операцию: чтение из несуществующей области памяти.
-> **ПРИМЕЧАНИЕ**: Эта программа не сработает, то есть не упадёт, на QEMU, потому что `qemu-system-arm -machine lm3s6965evb` не проверяет загрузки из памяти и спокойно возвращает `0 ` при чтении из недопустимой памяти.
+> **ПРИМЕЧАНИЕ**: Эта программа не сработает, то есть не упадёт, на QEMU, потому что `qemu-system-arm -machine lm3s6965evb` не проверяет загрузки из памяти и спокойно возвращает `0` при чтении из недопустимой памяти.
```rust,ignore
#![no_main]
diff --git a/embedded-book/src/start/hardware.md b/embedded-book/src/start/hardware.md
index 8843844..4addd00 100644
--- a/embedded-book/src/start/hardware.md
+++ b/embedded-book/src/start/hardware.md
@@ -39,22 +39,22 @@ $ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
$ cd app
```
-Первый шаг — задать таргет компиляции по умолчанию в `.cargo/config.toml`.
+Первый шаг — задать целевую платформу по умолчанию в `.cargo/config.toml`.
``` console
tail -n5 .cargo/config.toml
```
``` toml
-# Выберите ОДИН из этих таргетов компиляции
+# Выберите ОДНУ из этих целевых платформ
# target = "thumbv6m-none-eabi" # Cortex-M0 и Cortex-M0+
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 и Cortex-M7 (без FPU)
target = "thumbv7em-none-eabihf" # Cortex-M4F и Cortex-M7F (с FPU)
```
-Мы будем использовать `thumbv7em-none-eabihf`, так как он покрывает ядро Cortex-M4F.
-> **ПРИМЕЧАНИЕ**: как вы помните из предыдущей главы, все таргеты нужно установить, а этот — новый. Поэтому не забудьте выполнить установку командой `rustup target add thumbv7em-none-eabihf` для этого таргета.
+Мы будем использовать `thumbv7em-none-eabihf`, так как эта платформа подходит для ядра Cortex-M4F.
+> **ПРИМЕЧАНИЕ**: как вы помните из предыдущей главы, каждую целевую платформу нужно устанавливать, а эта — новая. Поэтому не забудьте выполнить `rustup target add thumbv7em-none-eabihf`.
Второй шаг — внести информацию об областях памяти в файл `memory.x`.
@@ -68,7 +68,7 @@ MEMORY
RAM : ORIGIN = 0x20000000, LENGTH = 40K
}
```
-> **ПРИМЕЧАНИЕ**: если по какой-то причине вы изменили файл `memory.x` после первой сборки для конкретного таргета, выполните `cargo clean` перед `cargo build`, так как `cargo build` может не отслеживать изменения в `memory.x`.
+> **ПРИМЕЧАНИЕ**: если по какой-то причине вы изменили файл `memory.x` после первой сборки для конкретной целевой платформы, выполните `cargo clean` перед `cargo build`, так как `cargo build` может не отслеживать изменения в `memory.x`.
Начнём снова с примера hello, но сначала нужно сделать небольшое изменение.
@@ -103,7 +103,7 @@ cargo build --example hello
[verify]: ../intro/install/verify.md
-В терминале запустите `openocd`, чтобы подключиться к ST-LINK на отладочной плате. Запускайте эту команду из корня шаблона: `openocd` найдёт файл `openocd.cfg`, в котором указано, какой файл интерфейса и какой файл таргета использовать.
+В терминале запустите `openocd`, чтобы подключиться к ST-LINK на отладочной плате. Запускайте эту команду из корня шаблона: `openocd` найдёт файл `openocd.cfg`, в котором указано, какой файл интерфейса и какой файл целевого устройства использовать.
``` console
cat openocd.cfg
diff --git a/embedded-book/src/start/interrupts.md b/embedded-book/src/start/interrupts.md
index 756047e..b70e4c6 100644
--- a/embedded-book/src/start/interrupts.md
+++ b/embedded-book/src/start/interrupts.md
@@ -13,7 +13,7 @@
* Задать нужный приоритет обработчика прерывания в контроллере прерываний;
* Разрешить обработчик прерывания в контроллере прерываний.
-Подобно исключениям, крейт cortex-m-rt предоставляет атрибут [`interrupt`] для объявления обработчиков прерываний. Однако этот атрибут доступен только тогда, когда включена функция device. Кроме того, атрибут не предназначен для прямого использования: попытка сделать это приведёт к ошибке компиляции.
+Подобно исключениям, крейт cortex-m-rt предоставляет атрибут [`interrupt`] для объявления обработчиков прерываний. Однако этот атрибут доступен только при включённом feature `device`. Кроме того, атрибут не предназначен для прямого использования: попытка сделать это приведёт к ошибке компиляции.
Вместо этого используйте повторно экспортированную версию атрибута interrupt, которую предоставляет крейт устройства (обычно сгенерированный с помощью svd2rust). Это гарантирует, что компилятор может проверить, существует ли прерывание на целевом устройстве. Список доступных прерываний и их позиций в таблице векторов прерываний обычно автоматически генерируется из файла SVD с помощью svd2rust.
diff --git a/embedded-book/src/start/panicking.md b/embedded-book/src/start/panicking.md
index ce890dc..d24546a 100644
--- a/embedded-book/src/start/panicking.md
+++ b/embedded-book/src/start/panicking.md
@@ -24,7 +24,7 @@
[`panic-handler`]: https://crates.io/keywords/panic-handler
-Программа выбирает одно из этих поведений, просто подключая соответствующий крейт. Тот факт, что поведение при панике задаётся в исходном коде приложения одной строкой, полезен не только как документация, но и может использоваться для изменения поведения при панике в зависимости от профиля сборки. Например:
+Программа выбирает одно из этих поведений, просто подключая соответствующий крейт. Тот факт, что поведение при панике задаётся в исходном коде приложения одной строкой, полезен не только как документация, но и позволяет менять поведение при панике в зависимости от профиля сборки. Например:
``` rust,ignore
#![no_main]
@@ -41,10 +41,10 @@ use panic_abort as _;
// ..
```
-В этом примере крейт подключает `panic-halt`, если его собирают с профилем dev (`cargo build`), и подключает `panic-abort`, если его собирают с профилем release (`cargo build --release`).
+В этом примере подключается крейт `panic-halt`, если сборка выполняется с профилем dev (`cargo build`), и `panic-abort`, если с профилем release (`cargo build --release`).
> Форма `use panic_abort as _;` используется, чтобы обработчик паники `panic_abort` попал в итоговый исполняемый файл, а компилятору было понятно, что мы не будем явно использовать ничего из этого крейта. Без переименования `as _` компилятор выдал бы предупреждение о неиспользуемом импорте.
-> Иногда можно встретить `extern crate panic_abort` вместо этого — более старый стиль, который использовался до издания 2018 года Rust и теперь должен применяться только для «sysroot»-крейтов (поставляемых вместе с самим Rust), таких как `proc_macro`, `alloc`, `std` и `test`.
+> Иногда вместо этого встречается `extern crate panic_abort` — более старый стиль, который использовался до издания Rust 2018 и теперь нужен только для «sysroot»-крейтов (поставляемых вместе с самим Rust), таких как `proc_macro`, `alloc`, `std` и `test`.
## Пример
diff --git a/embedded-book/src/start/qemu.md b/embedded-book/src/start/qemu.md
index 9e965d9..2aa806c 100644
--- a/embedded-book/src/start/qemu.md
+++ b/embedded-book/src/start/qemu.md
@@ -5,7 +5,7 @@
[LM3S6965]: http://www.ti.com/product/LM3S6965
**ВАЖНО**
-В этом руководстве мы будем называть проект «app». Всякий раз, когда вы видите слово «app», замените его на имя, которое вы выбрали для своего проекта. Либо можно назвать проект «app» и не делать эти подстановки.
+В этом руководстве мы будем называть проект «app». Всякий раз, когда вы видите слово «app», замените его на имя, которое вы выбрали для своего проекта. Либо назовите проект «app», и подстановки не понадобятся.
## Создание нестандартной программы на Rust
@@ -150,7 +150,7 @@ MEMORY
*/
```
-Следующий шаг — *кросс*-компиляция программы для архитектуры Cortex-M3. Это так же просто, как выполнить `cargo build --target $TRIPLE`, если вы знаете, каким должен быть таргет компиляции (`$TRIPLE`). К счастью, `.cargo/config.toml` в шаблоне уже содержит ответ:
+Следующий шаг — *кросс*-компиляция программы для архитектуры Cortex-M3. Это так же просто, как выполнить `cargo build --target $TRIPLE`, если вы знаете, какой должна быть целевая платформа (`$TRIPLE`). К счастью, `.cargo/config.toml` в шаблоне уже содержит ответ:
```console
tail -n6 .cargo/config.toml
@@ -158,20 +158,20 @@ tail -n6 .cargo/config.toml
```toml
[build]
-# Выберите ОДИН из этих таргетов компиляции
+# Выберите ОДНУ из этих целевых платформ
# target = "thumbv6m-none-eabi" # Cortex-M0 и Cortex-M0+
target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 и Cortex-M7 (без FPU)
# target = "thumbv7em-none-eabihf" # Cortex-M4F и Cortex-M7F (с FPU)
```
-Для кросс-компиляции под архитектуру Cortex-M3 нужно использовать `thumbv7m-none-eabi`. Этот таргет не устанавливается автоматически вместе с тулчейном Rust, поэтому сейчас самое время добавить его в тулчейн, если вы ещё этого не сделали:
+Для кросс-компиляции под архитектуру Cortex-M3 нужно использовать `thumbv7m-none-eabi`. Эта целевая платформа не устанавливается автоматически вместе с тулчейном Rust, поэтому сейчас самое время добавить его в тулчейн, если вы ещё этого не сделали:
``` console
rustup target add thumbv7m-none-eabi
```
-Поскольку таргет `thumbv7m-none-eabi` указан по умолчанию в вашем `.cargo/config.toml`, две команды ниже делают одно и то же:
+Поскольку целевая платформа `thumbv7m-none-eabi` указана по умолчанию в вашем `.cargo/config.toml`, две команды ниже делают одно и то же:
```console
cargo build --target thumbv7m-none-eabi
@@ -261,7 +261,7 @@ Total 14570
cargo objdump --bin app --release -- --disassemble --no-show-raw-insn --print-imm-hex
```
-> **ПРИМЕЧАНИЕ** если приведённая выше команда выдаёт `Unknown command line argument`, см. следующий баг-репорт: https://github.com/r007/EmbeddedRust-Rus/issues/269
+> **ПРИМЕЧАНИЕ** если приведённая выше команда выдаёт `Unknown command line argument`, см. следующий баг-репорт: https://github.com/rust-embedded/book/issues/269
> **ПРИМЕЧАНИЕ** этот вывод может отличаться в вашей системе. Новые версии rustc, LLVM и библиотек могут генерировать другой ассемблерный код. Мы сократили некоторые инструкции, чтобы фрагмент оставался компактным.
@@ -392,7 +392,7 @@ head -n3 .cargo/config.toml
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
```
-Этот runner применяется только к таргету `thumbv7m-none-eabi`, который является нашим таргетом компиляции по умолчанию. Теперь `cargo run` будет компилировать программу и запускать её на QEMU:
+Этот runner применяется только к целевой платформе `thumbv7m-none-eabi`, которая у нас выбрана по умолчанию. Теперь `cargo run` будет компилировать программу и запускать её на QEMU:
```console
cargo run --example hello --release
diff --git a/embedded-book/src/start/registers.md b/embedded-book/src/start/registers.md
index da95db1..7b7e622 100644
--- a/embedded-book/src/start/registers.md
+++ b/embedded-book/src/start/registers.md
@@ -2,12 +2,12 @@
Встраиваемые системы не могут обойтись только выполнением обычного кода на Rust и перемещением данных в ОЗУ. Если мы хотим передавать информацию в систему или из неё (будь то мигание светодиодом, обнаружение нажатия кнопки или обмен данными с внешней периферией по какой-либо шине), нам придётся заглянуть в мир периферии и её «регистров, отображённых в память».
-Скорее всего, код для доступа к периферии вашего микроконтроллера уже написан, и существует на одном из следующих уровней:
+Скорее всего, код для доступа к периферии вашего микроконтроллера уже написан и существует на одном из следующих уровней:
-* Крейт микроархитектуры — такой крейт содержит полезные подпрограммы, общие для ядра процессора, которое использует ваш микроконтроллер, а также для периферии, одинаковой для всех микроконтроллеров с таким типом ядра. Например, крейт [cortex-m] предоставляет функции для разрешения и запрета прерываний — они одинаковы для всех микроконтроллеров на базе Cortex-M. Он также даёт доступ к периферии 'SysTick', которая есть во всех микроконтроллерах на базе Cortex-M.
+* Крейт микроархитектуры — такой крейт содержит полезные подпрограммы, общие для ядра процессора, которое использует ваш микроконтроллер, а также для периферии, одинаковой для всех микроконтроллеров с таким типом ядра. Например, крейт [cortex-m] предоставляет функции для разрешения и запрета прерываний — они одинаковы для всех микроконтроллеров на базе Cortex-M. Он также даёт доступ к периферии «SysTick», которая есть во всех микроконтроллерах на базе Cortex-M.
* Peripheral Access Crate (PAC) — такой крейт представляет собой тонкую обёртку над регистрами, определёнными для конкретного номера модели микроконтроллера, который вы используете. Например, [tm4c123x] для серии Texas Instruments Tiva-C TM4C123 или [stm32f30x] для серии STM32F30x от ST Microelectronics. Здесь вы будете работать с регистрами напрямую, следуя инструкциям по работе каждой периферии, приведённым в техническом справочном руководстве вашего микроконтроллера.
* HAL-крейт — эти крейты предлагают более удобный API для вашего процессора, часто за счёт реализации общих трейтов, определённых в [embedded-hal]. Например, такой крейт может предлагать структуру `Serial` с конструктором, который принимает подходящий набор выводов GPIO и скорость передачи (baud rate), и функцию вроде `write_byte` для отправки данных. Подробнее о [embedded-hal] см. главу [Переносимость][Portability].
* Крейт платы — эти крейты идут на один шаг дальше HAL-крейтов: они заранее настраивают различную периферию и выводы GPIO под конкретный отладочный комплект или плату, которую вы используете, например [stm32f3-discovery] для платы STM32F3DISCOVERY.
@@ -117,7 +117,7 @@ pwm.ctl.write(|w| w.globalsync0().clear_bit());
pwm.ctl.modify(|r, w| w.globalsync0().clear_bit());
```
-Функция `modify` наглядно показывает мощь замыканий. В C нам пришлось бы прочитать значение во временную переменную, изменить нужные биты и записать значение обратно. При этом есть немалая возможность ошибиться:
+Функция `modify` наглядно показывает мощь замыканий. В C нам пришлось бы прочитать значение во временную переменную, изменить нужные биты и записать значение обратно. При этом легко допустить ошибку:
```C
uint32_t temp = pwm0.ctl.read();
diff --git a/embedded-book/src/start/semihosting.md b/embedded-book/src/start/semihosting.md
index 42fc954..1cdb295 100644
--- a/embedded-book/src/start/semihosting.md
+++ b/embedded-book/src/start/semihosting.md
@@ -82,7 +82,7 @@ $ echo $?
Ещё один совет: можно настроить поведение при панике так, чтобы оно вызывало `exit(EXIT_FAILURE)`. Это позволит писать `no_std`-тесты, которые проходят выполнение (run-pass), и запускать их на QEMU.
-Для удобства крейт `panic-semihosting` имеет функцию «exit», которая при включении вызывает `exit(EXIT_FAILURE)` после вывода сообщения о панике в stderr хоста.
+Для удобства у крейта `panic-semihosting` есть feature «exit», который при включении вызывает `exit(EXIT_FAILURE)` после вывода сообщения о панике в stderr хоста.
```rust,ignore
#![no_main]
@@ -114,13 +114,13 @@ $ echo $?
1
```
-**ПРИМЕЧАНИЕ**: чтобы включить эту функцию в `panic-semihosting`, отредактируйте раздел dependencies в вашем `Cargo.toml`, где указан `panic-semihosting`, следующим образом:
+**ПРИМЕЧАНИЕ**: чтобы включить этот feature в `panic-semihosting`, отредактируйте раздел dependencies в вашем `Cargo.toml`, где указан `panic-semihosting`, следующим образом:
``` toml
panic-semihosting = { version = "VERSION", features = ["exit"] }
```
-где `VERSION` — нужная версия. Подробнее о функциях зависимостей см. раздел [`specifying dependencies`] в книге Cargo.
+где `VERSION` — нужная версия. Подробнее о feature-флагах зависимостей см. раздел [`specifying dependencies`] в книге Cargo.
[`specifying dependencies`]:
https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
diff --git a/embedded-book/src/static-guarantees/design-contracts.md b/embedded-book/src/static-guarantees/design-contracts.md
index 8605594..a34008d 100644
--- a/embedded-book/src/static-guarantees/design-contracts.md
+++ b/embedded-book/src/static-guarantees/design-contracts.md
@@ -97,9 +97,9 @@ impl GpioConfig {
}
```
-Поскольку нам нужно обеспечивать соблюдение ограничений аппаратуры, мы в итоге много проверяем во время выполнения. Это тратит время и ресурсы, а такой код гораздо менее приятно использовать разработчику.
+Поскольку нам нужно обеспечивать соблюдение ограничений аппаратуры, мы в итоге много проверяем во время выполнения. Это тратит время и ресурсы, а работать с таким кодом разработчику гораздо менее приятно.
-## Типовые состояния (Type States)
+## Состояния в типах (type states)
Но что, если вместо этого мы будем использовать систему типов Rust, чтобы обеспечивать соблюдение правил переходов между состояниями? Посмотрите на этот пример:
diff --git a/embedded-book/src/static-guarantees/state-machines.md b/embedded-book/src/static-guarantees/state-machines.md
index 5374592..19b93c7 100644
--- a/embedded-book/src/static-guarantees/state-machines.md
+++ b/embedded-book/src/static-guarantees/state-machines.md
@@ -14,7 +14,7 @@
* Вход: подтянут к земле (Input: Pulled Low)
* Вход: подтянут к питанию (Input: Pulled High)
-Если периферия начинает в режиме `Disabled`, чтобы перейти в состояние `Input: High Resistance`, нужно выполнить следующие шаги:
+Если периферия находится в режиме `Disabled`, то чтобы перейти в состояние `Input: High Resistance`, нужно выполнить следующие шаги:
1. Disabled
2. Enabled
diff --git a/embedded-book/src/static-guarantees/zero-cost-abstractions.md b/embedded-book/src/static-guarantees/zero-cost-abstractions.md
index 41beb4e..2088576 100644
--- a/embedded-book/src/static-guarantees/zero-cost-abstractions.md
+++ b/embedded-book/src/static-guarantees/zero-cost-abstractions.md
@@ -17,7 +17,7 @@ let _ = size_of::>(); // == 0
struct Enabled;
```
-Структуры, определённые таким образом, называются типами нулевого размера (Zero Sized Types), поскольку они не содержат никаких реальных данных. Хотя на этапе компиляции эти типы ведут себя «настоящими» — их можно копировать, перемещать, брать от них ссылки и т. д., — оптимизатор полностью удалит их.
+Структуры, определённые таким образом, называются типами нулевого размера (Zero Sized Types), поскольку они не содержат никаких реальных данных. Хотя на этапе компиляции эти типы ведут себя как «настоящие» — их можно копировать, перемещать, брать от них ссылки и т. д., — оптимизатор полностью удалит их.
В этом фрагменте кода:
diff --git a/embedded-book/src/unsorted/speed-vs-size.md b/embedded-book/src/unsorted/speed-vs-size.md
index f2f4017..c31af5b 100644
--- a/embedded-book/src/unsorted/speed-vs-size.md
+++ b/embedded-book/src/unsorted/speed-vs-size.md
@@ -22,7 +22,7 @@ debug = true
### Оптимизация зависимостей
-Есть функция Cargo с именем [`profile-overrides`], которая позволяет переопределить уровень оптимизации зависимостей. Вы можете использовать эту функцию, чтобы оптимизировать все зависимости по размеру, оставляя при этом верхний крейт неоптимизированным и удобным для отладки.
+У Cargo есть возможность [`profile-overrides`], которая позволяет переопределять уровень оптимизации зависимостей. С её помощью можно оптимизировать все зависимости по размеру, оставляя при этом верхний крейт неоптимизированным и удобным для отладки.
Имейте в виду, что обобщённый (generic) код иногда может оптимизироваться вместе с крейтом, в котором он создаётся, а не с крейтом, в котором он определён. Если вы создаёте экземпляр обобщённой структуры в своём приложении и обнаруживаете, что она подтягивает код большого объёма, возможно, увеличение уровня оптимизации соответствующих зависимостей не даст эффекта.
@@ -66,7 +66,7 @@ section size addr
.bss 4 0x20000000
```
-Это уменьшение использования флеш-памяти примерно на 6 КиБ без потери удобства отладки верхнего крейта. Если вы зайдёте внутрь зависимости, то снова увидите сообщения ``, но обычно вам нужно отлаживать верхний крейт, а не зависимости. А если вам *действительно* нужно отладить зависимость, вы можете использовать функцию `profile-overrides`, чтобы исключить конкретную зависимость из оптимизации. Пример ниже:
+Это сокращение использования флеш-памяти примерно на 6 КиБ, причём верхний крейт остаётся удобным для отладки. Если вы зайдёте внутрь зависимости, то снова увидите сообщения ``, но обычно вам нужно отлаживать верхний крейт, а не зависимости. А если вам *действительно* нужно отладить зависимость, вы можете воспользоваться `profile-overrides`, чтобы исключить конкретную зависимость из оптимизации. Пример ниже:
``` toml
# ..
diff --git a/esp32-book/src/SUMMARY.md b/esp32-book/src/SUMMARY.md
index f22812c..a29e96f 100644
--- a/esp32-book/src/SUMMARY.md
+++ b/esp32-book/src/SUMMARY.md
@@ -97,7 +97,7 @@
- [Точность АЦП ESP32](./thermistor/esp32-non-linear.md)
- [Нелинейность](./thermistor/non-linear.md)
- [Уравнение B](./thermistor/b-equation.md)
- - [Уравнение Штейнхарта](./thermistor/steinhart.md)
+ - [Уравнение Стейнхарта](./thermistor/steinhart.md)
- [Схема](./thermistor/circuit.md)
- [Вывод значений АЦП](./thermistor/print-adc.md)
- [Температура на OLED-дисплее](./thermistor/oled/index.md)
diff --git a/esp32-book/src/bluetooth/trouble/ble-module.md b/esp32-book/src/bluetooth/trouble/ble-module.md
index 5c11d28..46755fb 100644
--- a/esp32-book/src/bluetooth/trouble/ble-module.md
+++ b/esp32-book/src/bluetooth/trouble/ble-module.md
@@ -25,7 +25,7 @@ use embassy_time::Timer;
use trouble_host::prelude::*;
```
-Let's define the maximum number of concurrent connections and L2CAP channels for the BLE stack:
+Зададим максимальное количество одновременных соединений и каналов L2CAP для стека BLE:
```rust
/// Максимальное число подключений
@@ -60,6 +60,6 @@ struct SensorService {
Структура Server представляет наш GATT-сервер и содержит SensorService. SensorService определяет две характеристики:
-- sensor_data: значение типа "u8", которое имитирует данные датчика в этом упражнении. Оно поддерживает операции read и notify, позволяя клиентам читать текущее значение датчика и получать уведомления при его изменении. Позже мы будем обновлять это значение в цикле, чтобы показать обновления в реальном времени. Когда освоите BLE, можно попробовать подключить настоящий датчик и отправлять данные на мобильное устройство.
+- sensor_data: значение типа `u8`, которое имитирует данные датчика в этом упражнении. Оно поддерживает операции read и notify, позволяя клиентам читать текущее значение датчика и получать уведомления при его изменении. Позже мы будем обновлять это значение в цикле, чтобы показать обновления в реальном времени. Когда освоите BLE, можно попробовать подключить настоящий датчик и отправлять данные на мобильное устройство.
- sensor_settings: логическое значение, которое поддерживает и запись, и чтение. Это позволяет клиентам настраивать параметры датчика и читать текущую конфигурацию. Так мы показываем, что значение можно изменить со стороны клиента.
diff --git a/esp32-book/src/bluetooth/trouble/running-ble-stack.md b/esp32-book/src/bluetooth/trouble/running-ble-stack.md
index c361ac0..4f820c9 100644
--- a/esp32-book/src/bluetooth/trouble/running-ble-stack.md
+++ b/esp32-book/src/bluetooth/trouble/running-ble-stack.md
@@ -11,7 +11,7 @@
```rust
-/// Run the BLE stack.
+/// Запускает BLE-стек.
pub async fn run(controller: C)
where
C: Controller,
diff --git a/esp32-book/src/buzzer/active-beep.md b/esp32-book/src/buzzer/active-beep.md
index 58c9324..824c7df 100644
--- a/esp32-book/src/buzzer/active-beep.md
+++ b/esp32-book/src/buzzer/active-beep.md
@@ -23,7 +23,7 @@ esp-generate --chip esp32 active-buzzer
## Код
-Мы настроим GPIO 33 как выходной вывод с начальным состоянием Low. К этому выводу подключён положительный контакт пищалки.
+Мы настроим GPIO 33 как выходной вывод с начальным состоянием Low. К этому выводу подключён положительный вывод пищалки.
```rust
let mut buzzer = Output::new(peripherals.GPIO33, Level::Low, OutputConfig::default());
diff --git a/esp32-book/src/buzzer/play-songs/code.md b/esp32-book/src/buzzer/play-songs/code.md
index 586ed9c..8748246 100644
--- a/esp32-book/src/buzzer/play-songs/code.md
+++ b/esp32-book/src/buzzer/play-songs/code.md
@@ -20,7 +20,7 @@ esp-generate --chip esp32 buzzer-song
### Вывод пищалки
-Мы зададим GPIO 33 как выходной вывод. К нему подключён положительный контакт пищалки.
+Мы зададим GPIO 33 как выходной вывод. К нему подключён положительный вывод пищалки.
```rust
let mut buzzer = peripherals.GPIO33;
diff --git a/esp32-book/src/buzzer/play-songs/index.md b/esp32-book/src/buzzer/play-songs/index.md
index 3aa4def..9c5b3a4 100644
--- a/esp32-book/src/buzzer/play-songs/index.md
+++ b/esp32-book/src/buzzer/play-songs/index.md
@@ -6,7 +6,7 @@
Я разбил код на модули Rust (в этом упражнении, как и раньше, можно обойтись одним файлом): [`music`](./music-module.md) и `got`.
-Для этого упражнения рекомендуется пассивная пищалка, хотя можно использовать и активную, и пассивную.
+Для этого упражнения рекомендуется пассивная пищалка, хотя подойдёт любая.
## ШИМ
Мы будем использовать ШИМ, чтобы менять частоту сигнала, подаваемого на пищалку, причём каждая частота соответствует определённой музыкальной ноте. Частота (нота) звучит заданное время, после чего переключается на следующую ноту в соответствии с нотным листом.
diff --git a/esp32-book/src/core-concepts/adc/adc-in-esp32.md b/esp32-book/src/core-concepts/adc/adc-in-esp32.md
index c67aeae..7c86a0a 100644
--- a/esp32-book/src/core-concepts/adc/adc-in-esp32.md
+++ b/esp32-book/src/core-concepts/adc/adc-in-esp32.md
@@ -4,7 +4,7 @@
Теперь, когда мы понимаем, как работает АЦП, посмотрим на АЦП оригинального ESP32 и научимся использовать его с Rust.
-Оригинальный ESP32 имеет два 12-битных SAR-АЦП и поддерживает до 18 каналов АЦП. Используемая нами плата ESP32 DevKit V1 выводит 15 из этих выводов АЦП.
+Оригинальный ESP32 имеет два 12-битных SAR-АЦП и поддерживает до 18 каналов АЦП. Используемая нами плата ESP32 DevKit V1 выводит 15 из них.
## Выводы АЦП на ESP32 DevKit V1
@@ -30,7 +30,7 @@ ESP32 может уменьшить входное напряжение до т
| Ослабление | Измеряемый диапазон входного напряжения |
| --- | ---: |
-| 0 дБ | 00 мВ ~ 950 мВ |
+| 0 дБ | 100 мВ ~ 950 мВ |
| 2,5 дБ | 100 мВ ~ 1250 мВ |
| 6 дБ | 150 мВ ~ 1750 мВ |
| 11 дБ | 150 мВ ~ 2450 мВ |
diff --git a/esp32-book/src/core-concepts/adc/index.md b/esp32-book/src/core-concepts/adc/index.md
index 2866d1b..208a52a 100644
--- a/esp32-book/src/core-concepts/adc/index.md
+++ b/esp32-book/src/core-concepts/adc/index.md
@@ -1,4 +1,4 @@
-{{#title Что такое АЦП (ADC): объяснение для ESP32 | impl Rust for ESP32}}
+{{#title Что такое АЦП (ADC): объяснение для ESP32 | impl Rust для ESP32}}
# АЦП (аналого-цифровой преобразователь, ADC)
diff --git a/esp32-book/src/core-concepts/pwm/index.md b/esp32-book/src/core-concepts/pwm/index.md
index e572366..4b82076 100644
--- a/esp32-book/src/core-concepts/pwm/index.md
+++ b/esp32-book/src/core-concepts/pwm/index.md
@@ -49,13 +49,13 @@
}
.anode {
- height: 50px; /* Longer pin for the anode */
+ height: 50px; /* Более длинная ножка — анод */
margin-right: 15px;
background-color: #666;
}
.cathode {
- height: 40px; /* Shorter pin for the cathode */
+ height: 40px; /* Более короткая ножка — катод */
margin-left: 15px;
background-color: #333;
position: absolute;
@@ -125,7 +125,7 @@
## Период и частота
Период — это общее время, за которое завершается один цикл «включено — выключено».
-Частота ШИМ-сигнала — это количество циклов, которые он совершает за одну секунду, измеряется в герцах (Гц). Частота обратна периоду. Поэтому более высокая частота означает более короткий период и более быстрое переключение между высоким и низким уровнями.
+Частота ШИМ-сигнала — это количество циклов, которые он совершает за одну секунду, измеряется в герцах (Гц). Частота обратно пропорциональна периоду. Поэтому более высокая частота означает более короткий период и более быстрое переключение между высоким и низким уровнями.
\\[
\text{Frequency (Hz)} = \\frac{1}{\text{Period (s)}}
diff --git a/esp32-book/src/core-concepts/pwm/mcpwm.md b/esp32-book/src/core-concepts/pwm/mcpwm.md
index 71f1800..3c44b87 100644
--- a/esp32-book/src/core-concepts/pwm/mcpwm.md
+++ b/esp32-book/src/core-concepts/pwm/mcpwm.md
@@ -21,7 +21,7 @@ MCPWM предназначен для управления моторами и
Это значит, что каждый такт длится 6,25 наносекунды (нс).
-Регистр PWM_CLK_PRESCALE (8 бит) в ESP32 позволяет настроить базовую частоту, делив её. Когда предделитель применён к базовой частоте, она фактически уменьшается. Результирующий период ШИМ вычисляется по формуле:
+Регистр PWM_CLK_PRESCALE (8 бит) в ESP32 позволяет настроить базовую частоту, разделив её. Когда предделитель применён к базовой частоте, она фактически уменьшается. Результирующий период ШИМ вычисляется по формуле:
\\[
\text{PWM Clock Period} = 6.25 \text{ns} \times (\text{Prescaler Value} + 1)
diff --git a/esp32-book/src/core-concepts/voltage-divider.md b/esp32-book/src/core-concepts/voltage-divider.md
index 9620e74..1b41501 100644
--- a/esp32-book/src/core-concepts/voltage-divider.md
+++ b/esp32-book/src/core-concepts/voltage-divider.md
@@ -28,7 +28,7 @@ V_{out} = 3.3V \times \frac{10 k\Omega}{10 k\Omega + 10 k\Omega} = 3.3V \times \
\\]
-Выходное напряжение \\( V_{out} \\) равно 1.65 В.
+Выходное напряжение \\( V_{out} \\) равно 1,65 В.
```rust,editable
@@ -111,7 +111,7 @@ canvas {
const vout = vin * (r2 / (r1 + r2));
document.getElementById('result').textContent =
- `Выходное напряжение (Vout): ${vout.toFixed(2)} V`;
+ `Выходное напряжение (Vout): ${vout.toFixed(2)} В`;
}
function drawZigZagResistor(ctx, x, y, width, height) {
@@ -167,7 +167,7 @@ canvas {
ctx.fillStyle = 'black';
ctx.font = '16px Arial';
- ctx.fillText(`V_in: ${vin.toFixed(2)} V`, 35, 94);
+ ctx.fillText(`V_in: ${vin.toFixed(2)} В`, 35, 94);
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(150, 100);
@@ -182,7 +182,7 @@ canvas {
ctx.lineTo(170, 130);
ctx.stroke();
- ctx.fillText(`R1: ${r1} Ω`, 200, 155);
+ ctx.fillText(`R1: ${r1} Ом`, 200, 155);
drawZigZagResistor(ctx, 170, 130, 23, 40);
ctx.beginPath();
@@ -190,7 +190,7 @@ canvas {
ctx.lineTo(170, 230);
ctx.stroke();
- ctx.fillText(`R2: ${r2} Ω`, 200, 256);
+ ctx.fillText(`R2: ${r2} Ом`, 200, 256);
drawZigZagResistor(ctx, 170, 230, 20, 40);
ctx.beginPath();
@@ -205,7 +205,7 @@ canvas {
ctx.moveTo(170, 200);
ctx.lineTo(270, 200);
ctx.stroke();
- ctx.fillText(`V_out: ${vout.toFixed(2)} V`, 280, 203);
+ ctx.fillText(`V_out: ${vout.toFixed(2)} В`, 280, 203);
}
updateAndCalculate();
diff --git a/esp32-book/src/e-ink/draw-text.md b/esp32-book/src/e-ink/draw-text.md
index 714635b..db24635 100644
--- a/esp32-book/src/e-ink/draw-text.md
+++ b/esp32-book/src/e-ink/draw-text.md
@@ -82,10 +82,10 @@ Timer::after(Duration::from_secs(5)).await;
## Вывод текста
-Теперь наконец выведем текст «impl Rust for ESP32» на экран в позицию (x=3, y=100). После этого обновим и перерисуем дисплей, чтобы показать текст. Также добавляем короткую задержку, чтобы изменения успели примениться.
+Теперь наконец выведем текст «impl Rust для ESP32» на экран в позицию (x=3, y=100). После этого обновим и перерисуем дисплей, чтобы показать текст. Также добавляем короткую задержку, чтобы изменения успели примениться.
```rust
-draw_text(&mut display, "impl Rust for ESP32", 3, 100);
+draw_text(&mut display, "impl Rust для ESP32", 3, 100);
epd.update_and_display_frame(&mut spi_dev, display.buffer(), &mut Delay)
.unwrap();
Timer::after(Duration::from_secs(5)).await;
@@ -213,7 +213,7 @@ async fn main(spawner: Spawner) -> ! {
.unwrap();
Timer::after(Duration::from_secs(5)).await;
- draw_text(&mut display, "impl Rust for ESP32", 3, 100);
+ draw_text(&mut display, "impl Rust для ESP32", 3, 100);
epd.update_and_display_frame(&mut spi_dev, display.buffer(), &mut Delay)
.unwrap();
Timer::after(Duration::from_secs(5)).await;
diff --git a/esp32-book/src/esp32-intro/esp32-family.md b/esp32-book/src/esp32-intro/esp32-family.md
index 4401ff1..678de33 100644
--- a/esp32-book/src/esp32-intro/esp32-family.md
+++ b/esp32-book/src/esp32-intro/esp32-family.md
@@ -80,7 +80,7 @@ SoC в первую очередь предназначены для встра
## Как найти?
-Если вы будете искать на сайте интернет-магазина, скорее всего, найдёте её под названием вроде «ESP32 Development Board (ESP-WROOM-32)». Ищите плату с модулем ESP32-WROOM-32 и 30-контактной разводкой, как показано ниже.
+Если вы будете искать на сайте интернет-магазина, скорее всего, найдёте её под названием вроде «ESP32 Development Board (ESP-WROOM-32)». Ищите плату с модулем ESP32-WROOM-32 и 30 выводами, как показано ниже.
Сравнить характеристики и выводы платы можно по этой картинке.
diff --git a/esp32-book/src/help.md b/esp32-book/src/help.md
index 6f178ec..bacb669 100644
--- a/esp32-book/src/help.md
+++ b/esp32-book/src/help.md
@@ -6,7 +6,7 @@
## 1. Сравните с рабочим кодом
-Проверьте полные примеры кода или клонируйте эталонный проект для сравнения. Внимательно просмотрите свой код и версии зависимостей в `Cargo.toml`. Ищите синтаксические и логические ошибки. Если нужная feature не включена или есть несовпадение features, обязательно включите нужные, как показано в упражнении.
+Проверьте полные примеры кода или клонируйте эталонный проект для сравнения. Внимательно просмотрите свой код и версии зависимостей в `Cargo.toml`. Ищите синтаксические и логические ошибки. Если нужный feature-флаг не включён или feature-флаги не совпадают, обязательно включите нужные, как показано в упражнении.
Если вы нашли несовпадение версий, либо адаптируйте код под новую версию (поищите решение сами: это отличный способ лучше разобраться в материале), либо обновите зависимости до тех версий, которые используются в руководстве.
diff --git a/esp32-book/src/index.md b/esp32-book/src/index.md
index 069eabe..febda82 100644
--- a/esp32-book/src/index.md
+++ b/esp32-book/src/index.md
@@ -2,7 +2,7 @@
# Введение
-В этой книге мы используем плату ESP32 DevKit v1 и язык Rust, чтобы собирать простые и интересные проекты. ESP32 — популярный микроконтроллер для IoT-приложений, и мы идём практическим путём: учимся, делая. Вы научитесь включать светодиод, когда в комнате темнеет, с помощью LDR; использовать ультразвуковой датчик, чтобы определить, что что-то находится рядом; управлять светодиодом по Wi-Fi; выводить изображения и текст на OLED-дисплей; проигрывать мелодии и звуковые сигналы на пищалке; управлять сервомотором и многое другое.
+В этой книге мы используем плату ESP32 DevKit v1 и язык Rust, чтобы собирать простые и интересные проекты. ESP32 — популярный микроконтроллер для IoT-приложений, и мы идём практическим путём: учимся, делая. Вы научитесь включать светодиод, когда в комнате темнеет, с помощью LDR; использовать ультразвуковой датчик, чтобы определить, что что-то находится рядом; управлять светодиодом по Wi-Fi; выводить изображения и текст на OLED-дисплей; проигрывать мелодии и звуковые сигналы на пищалке; управлять сервоприводом и многое другое.
Мы будем использовать среду `no_std` языка Rust. Программировать ESP32 можно и в среде std, но я считаю, что лучше начинать с no_std: так вы сможете применять ту же логику и при работе с другими микроконтроллерами.
@@ -31,7 +31,7 @@
## Лицензия
-Книга «impl Rust for ESP32» (этот проект) распространяется по следующим лицензиям:
+Книга «impl Rust для ESP32» (этот проект) распространяется по следующим лицензиям:
* Примеры кода и самостоятельные Cargo-проекты, содержащиеся в книге, распространяются на условиях как [MIT License], так и [Apache License v2.0].
* Текст книги распространяется на условиях лицензии Creative Commons [CC-BY-SA v4.0].
diff --git a/esp32-book/src/lcd/index.md b/esp32-book/src/lcd/index.md
index 1e45f6d..6be23c2 100644
--- a/esp32-book/src/lcd/index.md
+++ b/esp32-book/src/lcd/index.md
@@ -13,7 +13,7 @@
### Варианты с I2C
Некоторые варианты оснащены адаптером-переходником I2C, поэтому для связи можно использовать I2C. Главное преимущество варианта с I2C — меньшее количество соединений. Мы будем использовать ЖК-дисплей с адаптером I2C.
-Если вас интересуют ЖК-дисплеи с параллельным интерфейсом, см. [раздел о LCD](https://pico.implrust.com/lcd-display) в версии этой книги для Pico. Однако имейте в виду, что параллельный интерфейс требует больше выводов GPIO (зато такие дисплеи дешевле).
+Если вас интересуют ЖК-дисплеи с параллельным интерфейсом, см. [раздел о LCD](https://r007.github.io/EmbeddedRust-Rus/pico-pico/lcd-display/) в версии этой книги для Pico. Однако имейте в виду, что параллельный интерфейс требует больше выводов GPIO (зато такие дисплеи дешевле).
diff --git a/esp32-book/src/lcd/lcd-custom-char-generator.md b/esp32-book/src/lcd/lcd-custom-char-generator.md
index 6581275..bfeeba9 100644
--- a/esp32-book/src/lcd/lcd-custom-char-generator.md
+++ b/esp32-book/src/lcd/lcd-custom-char-generator.md
@@ -1,4 +1,4 @@
-{{#title Generate Custom LCD Characters for HD44780 Displays}}
+{{#title Генератор пользовательских символов для ЖК-дисплеев HD44780}}
# Генератор пользовательских символов LCD (сетка 5x8)
diff --git a/esp32-book/src/lcd/multi-custom-gen.md b/esp32-book/src/lcd/multi-custom-gen.md
index b5d4529..54bf687 100644
--- a/esp32-book/src/lcd/multi-custom-gen.md
+++ b/esp32-book/src/lcd/multi-custom-gen.md
@@ -1,4 +1,4 @@
-{{#title Multi Custom Character Generator for LCD1602 Displays}}
+{{#title Генератор нескольких пользовательских символов для LCD1602}}
# Генератор нескольких пользовательских символов
@@ -289,7 +289,7 @@
// Обработчики событий
gridSizeSelector.addEventListener('change', () => {
gridCount = parseInt(gridSizeSelector.value);
- validateLayout(); // Apply layout restriction
+ validateLayout(); // Применяем ограничение раскладки
createGrids(gridCount, gridLayoutSelector.value);
updateOutput(gridCount);
});
diff --git a/esp32-book/src/ldr/how-it-works.md b/esp32-book/src/ldr/how-it-works.md
index 6319bb5..a15c632 100644
--- a/esp32-book/src/ldr/how-it-works.md
+++ b/esp32-book/src/ldr/how-it-works.md
@@ -48,7 +48,7 @@ canvas {
@@ -87,7 +87,7 @@ canvas {
}
const vout = vin * (r2 / (r1 + r2));
document.getElementById('result').innerHTML =
- `Выходное напряжение (Vout): ${vout.toFixed(2)} V`;
+ `Выходное напряжение (Vout): ${vout.toFixed(2)} В`;
}
function drawZigZagResistor(ctx, x, y, width, height) {
const segments = 6;
@@ -140,8 +140,8 @@ canvas {
}
function formatResistance(resistance) {
return resistance >= 1000
- ? `${(resistance / 1000).toFixed(1)} kΩ`
- : `${resistance.toFixed(0)} Ω`;
+ ? `${(resistance / 1000).toFixed(1)} кОм`
+ : `${resistance.toFixed(0)} Ом`;
}
function drawCircuit() {
const canvas = document.getElementById('circuitCanvas');
@@ -162,7 +162,7 @@ canvas {
ctx.fillStyle = 'black';
ctx.font = '14px Arial';
- ctx.fillText(`V_in: ${vin.toFixed(2)} V`, 38, 96);
+ ctx.fillText(`V_in: ${vin.toFixed(2)} В`, 38, 96);
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(150, 100);
@@ -207,7 +207,7 @@ canvas {
ctx.moveTo(170, 200);
ctx.lineTo(270, 200);
ctx.stroke();
- ctx.fillText(`V_out: ${vout.toFixed(2)} V`, 280, 203);
+ ctx.fillText(`V_out: ${vout.toFixed(2)} В`, 280, 203);
}
updateAndCalculate();
diff --git a/esp32-book/src/ldr/led/index.md b/esp32-book/src/ldr/led/index.md
index 35cbd4b..96b73ed 100644
--- a/esp32-book/src/ldr/led/index.md
+++ b/esp32-book/src/ldr/led/index.md
@@ -14,7 +14,7 @@
- **LDR (светозависимый резистор)** — используется для определения интенсивности света.
- **Резисторы**
- **330 Ом** — для светодиода, чтобы ограничить ток и не допустить повреждения. (Может потребоваться подбор в зависимости от светодиода.)
- - **10 кОм** — для LDR, образующий делитель напряжения в схеме.
+ - **10 кОм** — для LDR; вместе с ним образует делитель напряжения.
- **Провода-перемычки** — для соединения компонентов на макетной плате или с микроконтроллером.
diff --git a/esp32-book/src/led/index.md b/esp32-book/src/led/index.md
index 51deec2..385c008 100644
--- a/esp32-book/src/led/index.md
+++ b/esp32-book/src/led/index.md
@@ -15,13 +15,13 @@
## Глаз
-"
+«
Подойдите ближе… Ещё ближе…
Чем больше вам кажется, что вы видите, тем легче вас обмануть…
Ведь что такое зрение?.. Вы смотрите, но на самом деле вы фильтруете, интерпретируете, ищете смысл…
-"
+»
В ШИМ мы задаём процент, который определяет, сколько времени сигнал остаётся в высоком (ВКЛ) и низком (ВЫКЛ) состоянии в каждом цикле. Например, при коэффициенте заполнения 50% сигнал включён половину времени и выключен другую половину, поэтому светодиод горит только половину цикла.
diff --git a/esp32-book/src/oled/draw-image/bitmap.md b/esp32-book/src/oled/draw-image/bitmap.md
index e76a796..dac8499 100644
--- a/esp32-book/src/oled/draw-image/bitmap.md
+++ b/esp32-book/src/oled/draw-image/bitmap.md
@@ -26,7 +26,7 @@ cp -r esp32-projects/old-image ~/YOUR_PROJECT_FOLDER/oled-bmp
## Обновляем Cargo.toml
-Нам понадобится ещё один крейт, "tinybmp", чтобы загрузить BMP-изображение.
+Нам понадобится ещё один крейт, `tinybmp`, чтобы загрузить BMP-изображение.
```toml
tinybmp = "0.6.0"
@@ -35,7 +35,7 @@ tinybmp = "0.6.0"
## Использование BMP-файла
-Поместите файл "ferris.bmp" в папку src. Код довольно простой: загрузите изображение как байты и передайте их в функцию `from_slice` у `Bmp`. Затем используйте результат с `Image`.
+Поместите файл `ferris.bmp` в папку `src`. Код довольно простой: загрузите изображение как байты и передайте их в функцию `from_slice` у `Bmp`. Затем используйте результат с `Image`.
```rust
// здесь обычный шаблонный код...
diff --git a/esp32-book/src/ratatui/hello-rust/mousefood.md b/esp32-book/src/ratatui/hello-rust/mousefood.md
index 0a34e5e..bfff713 100644
--- a/esp32-book/src/ratatui/hello-rust/mousefood.md
+++ b/esp32-book/src/ratatui/hello-rust/mousefood.md
@@ -6,7 +6,7 @@
## Предварительные требования
-- Для этой главы понадобится TFT-дисплей. Если вы ещё не прошли [главу о TFT-дисплее](../../tft-display/index.md), рекомендую сначала закончить её, а затем вернуться сюда. Поскольку схема подключения TFT-дисплея к ESP32 уже описана там, здесь мы не будем повторять эти инструкции.
+- Для этой главы понадобится TFT-дисплей. Если вы ещё не прошли [главу о TFT-дисплее](../../tft-display/index.md), рекомендую сначала закончить её, а затем вернуться сюда. Поскольку схема подключения TFT-дисплея к ESP32 уже описана там, здесь мы не будем повторять эти инструкции.
- У Ratatui есть хороший [учебник для начала](https://ratatui.rs/tutorials/hello-ratatui/) по созданию TUI-приложений. Если вы уже знаете Ratatui, это упражнение довольно простое: нужно просто соединить части вместе. Если вы новичок, позже изучите официальные руководства Ratatui, чтобы освоить основы и создавать более удобные интерфейсы.
diff --git a/esp32-book/src/rfid/access-bits-calculator.md b/esp32-book/src/rfid/access-bits-calculator.md
index a5957b2..c98beff 100644
--- a/esp32-book/src/rfid/access-bits-calculator.md
+++ b/esp32-book/src/rfid/access-bits-calculator.md
@@ -1,4 +1,4 @@
-{{#title MIFARE Classic 1K Access Bits Calculator for ESP32}}
+{{#title Калькулятор битов доступа MIFARE Classic 1K для ESP32}}
# Калькулятор битов доступа MIFARE Classic 1K
@@ -387,7 +387,7 @@
const table = row.closest('table');
let nestedTable = row.nextElementSibling;
- // Check if nested table already exists, otherwise create a new one
+ // Проверяем, существует ли вложенная таблица, иначе создаём новую
if (!nestedTable || !nestedTable.classList.contains('nested-table')) {
nestedTable = document.createElement('tr');
const td = document.createElement('td');
@@ -396,11 +396,11 @@
nestedTable.setAttribute('data-parent', rowId);
td.innerHTML = document.getElementById(tmplId).innerHTML;
nestedTable.appendChild(td);
- // Insert the nested table below the row
+ // Вставляем вложенную таблицу под строкой
row.insertAdjacentElement('afterend', nestedTable);
}
- // Toggle visibility of the nested table
+ // Переключаем видимость вложенной таблицы
nestedTable.style.display = nestedTable.style.display === 'none' || nestedTable.style.display === '' ? 'table-row' : 'none';
}
@@ -615,7 +615,7 @@
errorBox.style.display = 'none';
}
- // Function to determine permissions and acess from the bytes
+ // Функция определения прав и условий доступа по байтам
function decode() {
const accessBits = document.getElementById('access-bits').value;
@@ -631,19 +631,19 @@
const byte7 = accessBits.slice(2, 4); // Byte 7
const byte8 = accessBits.slice(4, 6); // Byte 8
- // Convert the byte strings to integers (assuming hexadecimal)
+ // Преобразуем строки с байтами в целые числа (считаем, что запись шестнадцатеричная)
const byteArray = [
- parseInt(byte6, 16), // Convert byte6 to an integer
- parseInt(byte7, 16), // Convert byte7 to an integer
- parseInt(byte8, 16) // Convert byte8 to an integer
+ parseInt(byte6, 16), // Преобразуем byte6 в целое число
+ parseInt(byte7, 16), // Преобразуем byte7 в целое число
+ parseInt(byte8, 16) // Преобразуем byte8 в целое число
];
- // Function to convert a byte to its corresponding bits array
+ // Функция преобразования байта в массив его битов
const byteToBits = (byte) => {
return Array.from({ length: 8 }, (_, i) => (byte >> (7 - i)) & 1);
};
- // Create a dictionary with byte keys and their corresponding bits array
+ // Создаём словарь: ключи — байты, значения — соответствующие массивы битов
const byteToBitsDict = {
"byte6": byteToBits(byteArray[0]),
"byte7": byteToBits(byteArray[1]),
@@ -669,7 +669,7 @@
};
let ICxy = {
- // Inverted values
+ // Инвертированные значения
"IC10": byteToBitsDict.byte6[7],
"IC20": byteToBitsDict.byte6[3],
"IC30": byteToBitsDict.byte7[7],
@@ -741,7 +741,7 @@
stRow.cells[9].textContent = stCols.remarks;
}
- // convert access and permission to bytes
+ // преобразуем права и условия доступа в байты
function encode() {
let byte6 = 0xFF;
let byte7 = 0x07;
@@ -771,7 +771,7 @@
};
let ICxy = {
- // Inverted values
+ // Инвертированные значения
"IC10": Cxy.C10 ^ 1,
"IC20": Cxy.C20 ^ 1,
"IC30": Cxy.C30 ^ 1,
diff --git a/esp32-book/src/rfid/access-bits.md b/esp32-book/src/rfid/access-bits.md
index c06c3f2..b5cc4e6 100644
--- a/esp32-book/src/rfid/access-bits.md
+++ b/esp32-book/src/rfid/access-bits.md
@@ -23,7 +23,7 @@
## Условия доступа
Начнём с главного: с условий доступа. Во время исследования я заметил, что многим людям трудно разобраться в разделе об условиях доступа в даташите. Вот моя попытка объяснить его понятно 🤞.
-Для управления правами каждого блока используются всего 3 битовые комбинации. В официальном даташите это обозначается как CXY (C1₀, C1₂... C3₃) для битов доступа. Первое число (X) в этой записи — номер бита доступа, от 1 до 3, каждый из которых соответствует определённому типу прав. Однако смысл этих прав меняется в зависимости от того, является ли блок блоком данных или трейлером. Второе число (Y) в подстрочном индексе обозначает относительный номер блока — от 0 до 3.
+Для управления правами каждого блока используется всего три бита, то есть одна из восьми комбинаций. В официальном даташите это обозначается как CXY (C1₀, C1₂... C3₃) для битов доступа. Первое число (X) в этой записи — номер бита доступа, от 1 до 3, каждый из которых соответствует определённому типу прав. Однако смысл этих прав меняется в зависимости от того, является ли блок блоком данных или трейлером. Второе число (Y) в подстрочном индексе обозначает относительный номер блока — от 0 до 3.
### Таблица 1: условия доступа для трейлера сектора
В оригинальном даташите подстрочный индекс в таблице не указан. Я добавил индекс «3», так как трейлер сектора находится в блоке 3.
diff --git a/esp32-book/src/rfid/change-auth-key.md b/esp32-book/src/rfid/change-auth-key.md
index e316aac..dd73fb0 100644
--- a/esp32-book/src/rfid/change-auth-key.md
+++ b/esp32-book/src/rfid/change-auth-key.md
@@ -18,7 +18,7 @@
2. Задаём `new_key` как `Rusted` (в hex-байтах). Это нужно, чтобы вывести содержимое блока после записи; иначе мы получим ошибку аутентификации.
3. Программа выведет содержимое блока до и после записи.
-Как только ключ обновлён, поднесите метку к считывателю снова. Скорее всего, вы увидите ошибку «Auth failed». Если интересно почему, — поздравляю, вы догадались! Новый ключ успешно записан, поэтому зашитый в код `current_key` больше не работает. Чтобы проверить, измените программу `read-data` так, чтобы она использовала новый ключ (`Rusted`), и попробуйте снова.
+Как только ключ обновлён, поднесите метку к считывателю снова. Скорее всего, вы увидите ошибку «Auth failed». Если вы уже догадались почему — поздравляю! Новый ключ успешно записан, поэтому зашитый в код `current_key` больше не работает. Чтобы проверить, измените программу `read-data` так, чтобы она использовала новый ключ (`Rusted`), и попробуйте снова.
### Ключ и данные
Массив `DATA` содержит новый ключ A («Rusted» в hex), биты доступа и ключ B («Ferris» в hex). `current_key` задан значением по умолчанию `FF FF FF FF FF FF`, а `new_key` — первыми 6 байтами `DATA`, то есть «Rusted».
diff --git a/esp32-book/src/rfid/index.md b/esp32-book/src/rfid/index.md
index 04a4b71..42dd90c 100644
--- a/esp32-book/src/rfid/index.md
+++ b/esp32-book/src/rfid/index.md
@@ -15,7 +15,7 @@
RFID (Radio Frequency Identification, радиочастотная идентификация) — это технология, которая использует радиоволны для идентификации и отслеживания предметов и животных. Она беспроводно передаёт сохранённые данные с метки (содержащей микросхему и антенну) считывателю, когда метка находится в зоне действия.
## Классификация по диапазону частот
-RFID-системы можно классифицировать по рабочей частоте. Основных типа три:
+RFID-системы можно классифицировать по рабочей частоте. Основных типов три:
- **Низкая частота (LF, Low Frequency)**: работает на частоте ~125 кГц с небольшой дальностью (до 10 см). Скорость ниже, обычно используется в системах контроля доступа и для учёта скота.
diff --git a/esp32-book/src/sdcard/index.md b/esp32-book/src/sdcard/index.md
index 878bd96..615fd54 100644
--- a/esp32-book/src/sdcard/index.md
+++ b/esp32-book/src/sdcard/index.md
@@ -25,9 +25,9 @@ SD-карты читают и записывают данные блоками,
Конечно, понадобится и сама microSD-карта. Её нужно отформатировать в FAT32. В зависимости от аппаратного обеспечения вашего компьютера может понадобиться отдельный адаптер SD-карт (не тот, что указан выше), чтобы отформатировать microSD-карту. Некоторые ноутбуки имеют прямую поддержку microSD-карт.
## Протокол
-Для работы с SD-картой можно использовать протокол SD Bus, протокол SPI или шину UHS-II. Raspberry Pi (но не Raspberry Pi Pico) использует протокол SD Bus, который сложнее, чем SPI. Полные подробности протокола SD Bus публично не доступны и предоставляются только через SD Association. В этом руководстве мы будем использовать протокол SPI, потому что драйвер на Rust, который мы применяем, рассчитан именно на него.
+Для работы с SD-картой можно использовать протокол SD Bus, протокол SPI или шину UHS-II. Raspberry Pi (но не Raspberry Pi Pico) использует протокол SD Bus, который сложнее, чем SPI. Полные подробности протокола SD Bus публично недоступны и предоставляются только через SD Association. В этом руководстве мы будем использовать протокол SPI, потому что драйвер на Rust, который мы применяем, рассчитан именно на него.
### Ссылки:
-- Настоятельно рекомендую посмотреть [доклад](https://www.youtube.com/watch?v=-ewuFNKIAVI) Джонатана Паланта на Euro Rust 2024 о написании драйвера SD-карты на Rust. Он написал драйвер, который мы будем использовать (изначально он создавал его, чтобы запускать MS-DOS на ARM). Драйвер не предназначен для производственных систем.
+- Настоятельно рекомендую посмотреть [доклад](https://www.youtube.com/watch?v=-ewuFNKIAVI) Джонатана Паланта на Euro Rust 2024 о написании драйвера SD-карты на Rust. Он написал драйвер, который мы будем использовать (изначально он создавал его, чтобы запускать MS-DOS на ARM). Драйвер не предназначен для промышленной эксплуатации.
- Если хотите понять, как всё работает внутри в режиме SPI, см. эту статью: [How to Use MMC/SDC](http://elm-chan.org/docs/mmc/mmc_e.html)
diff --git a/esp32-book/src/sdcard/read-sdcard.md b/esp32-book/src/sdcard/read-sdcard.md
index 35311c7..779e938 100644
--- a/esp32-book/src/sdcard/read-sdcard.md
+++ b/esp32-book/src/sdcard/read-sdcard.md
@@ -2,7 +2,7 @@
# Пишем код на Rust для чтения файла с SD-карты через ESP32
-Создадим простую программу, которая читает файл с SD-карты и выводит его содержимое в системную консоль. Убедитесь, что SD-карта отформатирована в FAT32 и содержит файл для чтения (например, "FERRIS.TXT" с содержимым "Hello, World!").
+Создадим простую программу, которая читает файл с SD-карты и выводит его содержимое в системную консоль. Убедитесь, что SD-карта отформатирована в FAT32 и содержит файл для чтения (например, `FERRIS.TXT` с содержимым «Hello, World!»).
## Создание проекта с помощью esp-generate
Мы включим поддержку async (Embassy) для этого проекта. Чтобы создать проект, используйте команду `esp-generate`. Выполните:
@@ -135,7 +135,7 @@ let root_dir = volume0.open_root_dir().unwrap();
### Открываем файл
-Откроем файл "FERRIS.TXT" в режиме только для чтения. Убедитесь, что вы заранее добавили этот файл на SD-карту с каким-нибудь содержимым.
+Откроем файл `FERRIS.TXT` в режиме только для чтения. Убедитесь, что вы заранее добавили этот файл на SD-карту с каким-нибудь содержимым.
```rust
let mut my_file = root_dir
diff --git a/esp32-book/src/servo/ledc.md b/esp32-book/src/servo/ledc.md
index 97b0c0c..e4276f7 100644
--- a/esp32-book/src/servo/ledc.md
+++ b/esp32-book/src/servo/ledc.md
@@ -66,7 +66,7 @@ fn duty_from_angle(deg: u32, min_duty: u32, duty_gap: u32) -> u16 {
}
```
-Например, если угол 180 градусов. Мы уже вычислили диапазон `min_duty` и `max_duty`, то есть 102 и 512, а разница между ними 410. Подставим в формулу.
+Например, возьмём угол 180 градусов. Мы уже вычислили диапазон `min_duty` и `max_duty`, то есть 102 и 512, а разница между ними 410. Подставим в формулу.
duty = 102 + ((180 * 410) / 180) = 512
diff --git a/esp32-book/src/tft-display/draw-text.md b/esp32-book/src/tft-display/draw-text.md
index 1679ae2..f9011f1 100644
--- a/esp32-book/src/tft-display/draw-text.md
+++ b/esp32-book/src/tft-display/draw-text.md
@@ -121,7 +121,7 @@ display.clear(Rgb565::WHITE).unwrap();
## Вывод текста
-Теперь наконец выведем текст «impl Rust for ESP32» на экран. Две части текста мы выведем отдельно, используя разные размеры шрифта и цвета.
+Теперь наконец выведем текст «impl Rust для ESP32» на экран. Две части текста мы выведем отдельно, используя разные размеры шрифта и цвета.
```rust
diff --git a/esp32-book/src/thermistor/esp32-non-linear.md b/esp32-book/src/thermistor/esp32-non-linear.md
index 483e64b..ed4318d 100644
--- a/esp32-book/src/thermistor/esp32-non-linear.md
+++ b/esp32-book/src/thermistor/esp32-non-linear.md
@@ -4,7 +4,7 @@
В ранних версиях чипа ESP32, например в том, что установлен на DevKit V1 (скорее всего, он у вас тоже есть), АЦП имеет проблему нелинейности. Когда я использовал сырое значение АЦП для расчёта температуры, результаты постоянно выходили неверными. Это сбивало меня с толку несколько дней, пока я не наткнулся на статью [Using a Thermistor with Arduino and Unexpected ESP32 ADC Non-linearity](https://www.e-tinkers.com/2019/10/using-a-thermistor-with-arduino-and-unexpected-esp32-adc-non-linearity/). В ней объяснялась проблема нелинейности АЦП ESP32.
-Решение — использовать таблицу поиска (LUT), которая сопоставляет сырое значение АЦП с исправленным. Однако значения таблицы различаются от устройства к устройству, потому что у каждого ESP32 свое внутреннее опорное напряжение, поэтому использовать её как есть может не получиться. В репозитории «[esp32-adc-calibrate](https://github.com/e-tinkers/esp32-adc-calibrate)» есть код для генерации собственной LUT для вашего ESP32.
+Решение — использовать таблицу поиска (LUT), которая сопоставляет сырое значение АЦП с исправленным. Однако значения таблицы различаются от устройства к устройству, потому что у каждого ESP32 своё внутреннее опорное напряжение, поэтому использовать её как есть может не получиться. В репозитории «[esp32-adc-calibrate](https://github.com/e-tinkers/esp32-adc-calibrate)» есть код для генерации собственной LUT для вашего ESP32.
Я запустил программу калибровки для своего ESP32 и сгенерировал таблицу поиска (LUT) для своего устройства. Её я привожу ниже. Она должна примерно подойти для ESP32 DevKit V1, но помните, что характеристики АЦП ESP32 различаются от устройства к устройству, поэтому LUT не гарантирует точности на вашей плате.
diff --git a/esp32-book/src/thermistor/index.md b/esp32-book/src/thermistor/index.md
index 16e4e1a..d957f8a 100644
--- a/esp32-book/src/thermistor/index.md
+++ b/esp32-book/src/thermistor/index.md
@@ -4,7 +4,7 @@
В этом разделе мы будем использовать термистор с ESP32. Термистор — это переменный резистор, который меняет своё сопротивление в зависимости от температуры. Величина изменения сопротивления зависит от его состава. Название происходит от слияния слов «thermal» (тепловой) и «resistor» (резистор).
-Термисторы применяют для измерения температуры или защиты цепей во многих местах. С их помощью измеряют температуру масла и охлаждающей жидкости в автомобилях, их используют в медицинском оборудовании. В домашней автоматике термисторы встречаются в умных термостатах, которые управляют отоплением и охлаждением, поддерживая комфортную температуру. Мы будем использовать термистор, чтобы измерять комнатную температуру и выводить результат.
+Термисторы широко применяют для измерения температуры и защиты цепей. С их помощью измеряют температуру масла и охлаждающей жидкости в автомобилях, их используют в медицинском оборудовании. В домашней автоматике термисторы встречаются в умных термостатах, которые управляют отоплением и охлаждением, поддерживая комфортную температуру. Мы будем использовать термистор, чтобы измерять комнатную температуру и выводить результат.
Термисторы делятся на два типа:
- NTC (Negative Temperature Coefficient, с отрицательным температурным коэффициентом):
diff --git a/esp32-book/src/thermistor/non-linear.md b/esp32-book/src/thermistor/non-linear.md
index f0dd56c..1809639 100644
--- a/esp32-book/src/thermistor/non-linear.md
+++ b/esp32-book/src/thermistor/non-linear.md
@@ -1,14 +1,14 @@
# Нелинейность термистора
-У термисторов связь между сопротивлением и температурой нелинейна: при изменении температуры сопротивление меняется не по прямой линии. Поведение термисторов можно описать с помощью уравнения Штейнхарта — Харта или B-уравнения.
+У термисторов связь между сопротивлением и температурой нелинейна: при изменении температуры сопротивление меняется не по прямой линии. Поведение термисторов можно описать с помощью уравнения Стейнхарта — Харта или B-уравнения.
-B-уравнение просто рассчитать, используя B-значение, которое можно найти в даташите термистора или у производителя. Уравнение Штейнхарта — Харта использует коэффициенты A, B и C. Некоторые производители предоставляют эти коэффициенты для своих термисторов. Когда подходящие коэффициенты доступны, уравнение Штейнхарта — Харта может дать более точные расчёты температуры в более широком диапазоне.
+B-уравнение просто рассчитать, используя B-значение, которое можно найти в даташите термистора или у производителя. Уравнение Стейнхарта — Харта использует коэффициенты A, B и C. Некоторые производители предоставляют эти коэффициенты для своих термисторов. Когда подходящие коэффициенты доступны, уравнение Стейнхарта — Харта может дать более точные расчёты температуры в более широком диапазоне.
-В следующих главах мы подробно разберём, как использовать B-уравнение и уравнение Штейнхарта — Харта для определения температуры.
+В следующих главах мы подробно разберём, как использовать B-уравнение и уравнение Стейнхарта — Харта для определения температуры.
### Ссылки
-- [B-параметр и уравнение Штейнхарта — Харта](https://blog.meteodrenthe.nl/2022/09/07/the-b-parameter-vs-steinhart-hart-equation/)
-- [Характеристики термисторов: краткое введение, B-значение и коэффициенты Штейнхарта — Харта](https://community.element14.com/challenges-projects/design-challenges/experimenting-with-thermistors/b/challenge-blog/posts/blog-3-characterising-thermistors-a-quick-primer-beta-value-steinhart-hart-coefficients)
+- [B-параметр и уравнение Стейнхарта — Харта](https://blog.meteodrenthe.nl/2022/09/07/the-b-parameter-vs-steinhart-hart-equation/)
+- [Характеристики термисторов: краткое введение, B-значение и коэффициенты Стейнхарта — Харта](https://community.element14.com/challenges-projects/design-challenges/experimenting-with-thermistors/b/challenge-blog/posts/blog-3-characterising-thermistors-a-quick-primer-beta-value-steinhart-hart-coefficients)
diff --git a/esp32-book/src/thermistor/oled/index.md b/esp32-book/src/thermistor/oled/index.md
index 6b865c5..cc25772 100644
--- a/esp32-book/src/thermistor/oled/index.md
+++ b/esp32-book/src/thermistor/oled/index.md
@@ -15,7 +15,7 @@
## Требования к оборудованию
-- OLED-дисплей: (0,96 дюйма, I2C/IIC, 4 контакта, разрешение 128x64, чип SSD1306)
+- OLED-дисплей: (0,96 дюйма, I2C/IIC, 4 вывода, разрешение 128x64, чип SSD1306)
- Провода-перемычки
- Термистор NTC 103: 10 кОм, 5 мм, дисковый в эпоксидном покрытии
- Резистор 10 кОм: используется вместе с термистором для формирования делителя напряжения
@@ -29,7 +29,7 @@
1. Один вывод термистора подключён к `GND`.
2. Другой вывод термистора подключён к `GPIO13`, который является выводом ADC2 ESP32.
-3. Резистор 10 кОм подключается последовательно с термистором, образуя делитель напряжения между термистором и `3.3v`. Поэтому один вывод резистора подключите к `3.3V`, а другой — к `GPIO13`.
+3. Резистор 10 кОм подключается последовательно с термистором, образуя делитель напряжения между термистором и `3.3V`. Поэтому один вывод резистора подключите к `3.3V`, а другой — к `GPIO13`.
### Подключение OLED к ESP32
diff --git a/esp32-book/src/thermistor/steinhart.md b/esp32-book/src/thermistor/steinhart.md
index 4e8cc04..7ce6bbf 100644
--- a/esp32-book/src/thermistor/steinhart.md
+++ b/esp32-book/src/thermistor/steinhart.md
@@ -1,12 +1,12 @@
-{{#title Расчёт температуры термистора по уравнению Штейнхарта — Харта на ESP32 на Rust}}
+{{#title Расчёт температуры термистора по уравнению Стейнхарта — Харта на ESP32 на Rust}}
-# Уравнение Штейнхарта — Харта
+# Уравнение Стейнхарта — Харта
> [!TIP]
>
> В нашем упражнении мы не будем использовать это уравнение, потому что найти константы A, B и C сложнее. B-уравнения достаточно для наших целей, так что, если хотите, можете пропустить эту главу.
-Уравнение Штейнхарта — Харта даёт более точную зависимость между температурой и сопротивлением в широком диапазоне температур.
+Уравнение Стейнхарта — Харта даёт более точную зависимость между температурой и сопротивлением в широком диапазоне температур.
\\[
\frac{1}{T} = A + B \ln R + C (\ln R)^3
\\]
@@ -23,7 +23,7 @@
- B соответствует комнатной температуре, и
- C соответствует температуре горячей воды.
-### Расчёт коэффициентов Штейнхарта — Харта
+### Расчёт коэффициентов Стейнхарта — Харта
По трём точкам «сопротивление — температура» можно найти A, B и C.
@@ -353,7 +353,7 @@ function calculateTemperatureFromResistance() {
return;
}
- // Вычисляем температуру в кельвинах по уравнению Штейнхарта — Харта:
+ // Вычисляем температуру в кельвинах по уравнению Стейнхарта — Харта:
// 1/T = A + B*ln(R) + C*(ln(R))^3
let inverseTemperature = A + B * Math.log(resistance) + C * Math.pow(Math.log(resistance), 3);
let temperatureKelvin = 1 / inverseTemperature;
@@ -380,7 +380,7 @@ fn steinhart_temp_calc(
return Err("Resistance must be a positive number.".to_string());
}
- // Вычисляем температуру в кельвинах по уравнению Штейнхарта — Харта:
+ // Вычисляем температуру в кельвинах по уравнению Стейнхарта — Харта:
// 1/T = A + B*ln(R) + C*(ln(R))^3
let ln_r = resistance.ln();
let inverse_temperature = a + b * ln_r + c * ln_r.powi(3);
diff --git a/esp32-book/src/ultrasonic/how-it-works.md b/esp32-book/src/ultrasonic/how-it-works.md
index 7ece3f2..5a8844d 100644
--- a/esp32-book/src/ultrasonic/how-it-works.md
+++ b/esp32-book/src/ultrasonic/how-it-works.md
@@ -1,4 +1,4 @@
-{{#title Как работают ультразвуковые датчики HC-SR04 | impl Rust for ESP32}}
+{{#title Как работают ультразвуковые датчики HC-SR04 | impl Rust для ESP32}}
# Как работает ультразвуковой датчик?
diff --git a/esp32-book/src/wifi/embassy/async-access-website.md b/esp32-book/src/wifi/embassy/async-access-website.md
index 954890a..d917c2e 100644
--- a/esp32-book/src/wifi/embassy/async-access-website.md
+++ b/esp32-book/src/wifi/embassy/async-access-website.md
@@ -50,7 +50,7 @@ embassy-net = { version = "0.7.1", features = [
### smoltcp
-Крейт smoltcp тоже добавляется в Cargo.toml. Чтобы использовать DNS-серверы, нужно добавить функцию «dns-max-server-count-4».
+Крейт smoltcp тоже добавляется в Cargo.toml. Чтобы использовать DNS-серверы, нужно включить feature «dns-max-server-count-4».
```toml
# Обновлённый smoltcp в Cargo.toml
diff --git a/esp32-book/src/wifi/embassy/connecting-wifi.md b/esp32-book/src/wifi/embassy/connecting-wifi.md
index 210a8ba..cf5f759 100644
--- a/esp32-book/src/wifi/embassy/connecting-wifi.md
+++ b/esp32-book/src/wifi/embassy/connecting-wifi.md
@@ -21,7 +21,7 @@ macro_rules! mk_static {
}
```
-## Initializing the Wi-Fi Controller
+## Инициализация контроллера Wi-Fi
Инициализируем Embassy обычным образом:
diff --git a/esp32-book/src/wifi/led/index.md b/esp32-book/src/wifi/led/index.md
index 72c8b47..ec97e31 100644
--- a/esp32-book/src/wifi/led/index.md
+++ b/esp32-book/src/wifi/led/index.md
@@ -42,7 +42,7 @@ Serde — это крейт Rust для сериализации и десери
```toml
serde = { version = "1.0.228", default-features = false, features = ["derive"] }
-# Включаем функцию «json»
+# Включаем feature «json»
picoserve = { version = "0.17.1", features = ["embassy", "json"] }
```
diff --git a/esp32-book/src/wifi/web-server/exposing-to-internet.md b/esp32-book/src/wifi/web-server/exposing-to-internet.md
index eaab22a..b35edcc 100644
--- a/esp32-book/src/wifi/web-server/exposing-to-internet.md
+++ b/esp32-book/src/wifi/web-server/exposing-to-internet.md
@@ -2,7 +2,7 @@
# Открываем веб-сервер ESP32 в интернет
-Обычно не рекомендуется открывать из интернета IoT-веб-серверы, например те, что работают на ESP32, без должных мер безопасности. Такие устройства могут быть уязвимы для атак, например для несанкционированного доступа, включения в ботнет или других видов ущерба, в зависимости от устройства (на моём месте я бы не стал рисковать). Кроме того, использовать ESP32 как веб-хостинг непрактично из-за таких сложностей, как открытие портов, обработка нагрузки трафика и потенциальные риски безопасности. Тем не менее это может быть отличным учебным опытом, если хотите попробовать или показать друзьям.
+Обычно не рекомендуется открывать из интернета IoT-веб-серверы, например те, что работают на ESP32, без должных мер безопасности. Такие устройства могут быть уязвимы для атак, например для несанкционированного доступа, включения в ботнет или других видов ущерба, в зависимости от устройства (на вашем месте я бы не стал рисковать). Кроме того, использовать ESP32 как веб-хостинг непрактично из-за таких сложностей, как открытие портов, обработка нагрузки трафика и потенциальные риски безопасности. Тем не менее это может быть отличным учебным опытом, если хотите попробовать или показать друзьям.
## Проброс портов на роутере
diff --git a/esp32-book/src/wifi/web-server/index.md b/esp32-book/src/wifi/web-server/index.md
index a0fa27b..4656b55 100644
--- a/esp32-book/src/wifi/web-server/index.md
+++ b/esp32-book/src/wifi/web-server/index.md
@@ -63,7 +63,7 @@ picoserve = { version = "0.17.1", features = ["embassy"] }
## Модуль lib
-Перенесём макрос mk_static, который позволяет создавать статические переменные, инициализируемые во время выполнения, в модуль lib. Кроме того, включим функцию impl_trait_in_assoc_type, которую требует крейт picoserve.
+Перенесём макрос mk_static, который позволяет создавать статические переменные, инициализируемые во время выполнения, в модуль lib. Кроме того, включим нестабильную возможность языка (feature gate) `impl_trait_in_assoc_type`, которую требует крейт picoserve.
```rust
#![no_std]
diff --git a/esp32-book/src/wifi/web-server/serve-website.md b/esp32-book/src/wifi/web-server/serve-website.md
index b03af11..aea8358 100644
--- a/esp32-book/src/wifi/web-server/serve-website.md
+++ b/esp32-book/src/wifi/web-server/serve-website.md
@@ -4,8 +4,8 @@
Типовой код для подключения Wi-Fi готов. Далее с помощью крейта picoserve настроим маршрут для корневого URL («/»), который будет отдавать нашу HTML-страницу.
-## Функция `impl_trait_in_assoc_type`
-Крейту picoserve нужна функция `impl_trait_in_assoc_type`, которая в Rust пока является нестабильной. Чтобы её включить, добавьте следующую строку в начало файла lib.rs (мы уже сделали это):
+## Нестабильная возможность `impl_trait_in_assoc_type`
+Крейту picoserve нужна возможность языка `impl_trait_in_assoc_type`, которая в Rust пока нестабильна. Чтобы её включить, добавьте следующую строку в начало файла lib.rs (мы уже сделали это):
```rust
#![feature(impl_trait_in_assoc_type)]
```
@@ -105,8 +105,8 @@ pub async fn web_task(
```
-## Clone the existing project
-You can also clone (or refer) project I created and navigate to the `webserver-html` folder.
+## Клонирование существующего проекта
+Можно клонировать проект, который я создал (или просто посмотреть его), и перейти в папку `webserver-html`.
```sh
git clone https://github.com/ImplFerris/esp32-projects
diff --git a/esp32-book/src/wifi/web-server/wifi.md b/esp32-book/src/wifi/web-server/wifi.md
index 6814716..abe19a1 100644
--- a/esp32-book/src/wifi/web-server/wifi.md
+++ b/esp32-book/src/wifi/web-server/wifi.md
@@ -1,4 +1,4 @@
-{{#title ESP32 Wi-Fi Connection Module with Embassy and Rust}}
+{{#title Модуль подключения ESP32 к Wi-Fi на Embassy и Rust}}
# Модуль Wi-Fi
diff --git a/no-std-training/training-ru/application/project-overview.md b/no-std-training/training-ru/application/project-overview.md
index 47fbba3..2c74078 100644
--- a/no-std-training/training-ru/application/project-overview.md
+++ b/no-std-training/training-ru/application/project-overview.md
@@ -2,7 +2,7 @@
В этом курсе мы создадим простое приложение-регистратор данных. Оно подключится к сети Wi-Fi, будет считывать данные с датчика и отправлять их на брокер MQTT.
-Цель курса — получить приложение, которое похоже на «настоящий» проект и охватывает, по нашему мнению, важные темы, но при этом не требует написать тысячи строк кода до получения готового продукта.
+Цель курса — получить приложение, которое похоже на «настоящий» проект и охватывает, по нашему мнению, важные темы, но при этом не требует писать тысячи строк кода, чтобы получить готовый результат.
- Сначала в [настройке проекта](./project-setup.md) мы проведём вас через инициализацию проекта: сгенерируем новый шаблонный проект и объясним его составные части.
- В [чтении данных с датчика](./reading-sensor-data.md) мы начнём с инициализации устройства, чтобы плата была правильно настроена и готова к работе. Затем мы будем считывать данные с подключённого датчика температуры и влажности по шине I2C.
diff --git a/no-std-training/training-ru/application/project-setup.md b/no-std-training/training-ru/application/project-setup.md
index ba23389..abf4017 100644
--- a/no-std-training/training-ru/application/project-setup.md
+++ b/no-std-training/training-ru/application/project-setup.md
@@ -47,7 +47,7 @@ no_std-training/
- Переданы флаги компилятора Rust, которые принудительно включают frame pointers. Это необходимо для корректной работы бэктрейсов. Если вы не используете крейт `esp-backtrace`, это не требуется.
- Кроме того, мы настраиваем [espflash] как раннер Cargo для проекта.
- [`.clippy.toml`] содержит конфигурацию [Clippy], линтера для кода на Rust.
-- [`build.rs`] настраивает компилятор Rust так, чтобы подключались необходимые линкерные скрипты.
+- [`build.rs`] настраивает компилятор Rust так, чтобы подключались необходимые скрипты компоновщика.
- Это можно было бы задать и в `.cargo/config.toml`, но такой подход даёт более понятные диагностические сообщения при ошибках сборки.
- `Cargo.toml` — [манифест Cargo][Cargo manifest], в котором хранятся метаданные проекта, зависимости и другая информация.
- [`rust-toolchain.toml`] задаёт, какой тулчейн Rust использовать, а также указывает нужные компоненты и целевую платформу.
@@ -109,8 +109,8 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
-// This creates a default app-descriptor required by the ESP-IDF bootloader.
-// For more information see:
+// Создаёт дескриптор приложения по умолчанию, который требуется загрузчику ESP-IDF.
+// Подробнее см.:
esp_bootloader_esp_idf::esp_app_desc!();
#[allow(
@@ -128,14 +128,14 @@ async fn main(spawner: Spawner) -> ! {
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
- // TODO: Spawn some tasks
+ // TODO: запустить задачи
let _ = spawner;
loop {
Timer::after(Duration::from_secs(1)).await;
}
- // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/main/examples
+ // для вдохновения посмотрите примеры по адресу https://github.com/esp-rs/esp-hal/tree/main/examples
}
```
diff --git a/no-std-training/training-ru/application/publishing-data.md b/no-std-training/training-ru/application/publishing-data.md
index 2f446a7..0ddbbc2 100644
--- a/no-std-training/training-ru/application/publishing-data.md
+++ b/no-std-training/training-ru/application/publishing-data.md
@@ -34,7 +34,7 @@ MQTT — протокол «публикация/подписка» (publish/sub
{{#include ../../project/part3/Cargo.toml:rust_mqtt}}
```
-Функции по умолчанию отключены, потому что это приложение `no_std`. Фича `v5` включает MQTT версии 5, которая соответствует локальному брокеру, а `bump` включает хранение в bump-буфере крейта. Bump-буфер заранее резервирует блок памяти фиксированного размера и позволяет клиенту использовать его для пакетов MQTT без отдельного выделения кучи для каждой операции.
+Feature-флаги по умолчанию отключены, потому что это приложение `no_std`. Feature `v5` включает MQTT версии 5, которая соответствует локальному брокеру, а `bump` включает хранение в bump-буфере крейта. Bump-буфер заранее резервирует блок памяти фиксированного размера и позволяет клиенту использовать его для пакетов MQTT без отдельного выделения кучи для каждой операции.
## Запуск задачи MQTT
@@ -72,7 +72,7 @@ MQTT работает поверх TCP, поэтому задача не мож
{{#shiftinclude auto:../../project/part3/src/mqtt.rs:wait_network}}
```
-`wait_link_up()` ждёт канала Wi-Fi. `wait_config_up()` ждёт сетевой конфигурации, а `config_v4()` подтверждает, что IPv4-адрес доступен. Если конфигурация пропадёт до начала подключения к брокеру, внешний цикл начнёт последовательность заново.
+`wait_link_up()` ждёт, пока поднимется канал Wi-Fi. `wait_config_up()` ждёт сетевой конфигурации, а `config_v4()` подтверждает, что IPv4-адрес доступен. Если конфигурация пропадёт до начала подключения к брокеру, внешний цикл начнёт последовательность заново.
### Поиск брокера
diff --git a/no-std-training/training-ru/application/reading-sensor-data.md b/no-std-training/training-ru/application/reading-sensor-data.md
index e9bd990..cc9add5 100644
--- a/no-std-training/training-ru/application/reading-sensor-data.md
+++ b/no-std-training/training-ru/application/reading-sensor-data.md
@@ -16,7 +16,7 @@
{{#include ../../project/part1/src/main.rs:backtrace_import}}
```
-Фича `panic-handler` крейта `esp-backtrace` предоставляет обработчик паники за нас, а также даёт полезную поддержку бэктрейсов, когда что-то идёт не так.
+Feature `panic-handler` крейта `esp-backtrace` предоставляет обработчик паники за нас, а также даёт полезную поддержку бэктрейсов, когда что-то идёт не так.
### Логгер
@@ -28,7 +28,7 @@
Это позволяет использовать стандартные макросы [`log`]. В этой главе мы используем `info!` для вывода успешных показаний температуры и влажности, а `error!` — для сообщений о сбоях при запуске или чтении измерения.
-`init_logger_from_env()` настраивает логирование по переменной окружения `ESP_LOG`. Её значение похоже на фильтрацию `RUST_LOG`, которая используется в [`env_logger`][env-logger]. Переменную можно задать при сборке или запуске приложения:
+`init_logger_from_env()` настраивает логирование по переменной окружения `ESP_LOG`. Формат значения похож на формат фильтров `RUST_LOG` из [`env_logger`][env-logger]. Переменную можно задать при сборке или запуске приложения:
```shell
ESP_LOG=info cargo run --release
@@ -54,7 +54,7 @@ ESP_LOG=warn,no_std_training=info cargo run --release
### `esp_hal::init`
-[`esp_hal::Config`][esp-hal-config] описывает системную конфигурацию, которая применяется при инициализации HAL. Это `non-exhaustive` тип, поэтому мы создаём его с помощью `Config::default()`, а затем изменяем нужные параметры. В нашем приложении мы используем `with_cpu_clock(CpuClock::max())`, чтобы запросить максимальную тактовую частоту ЦП:
+[`esp_hal::Config`][esp-hal-config] описывает системную конфигурацию, которая применяется при инициализации HAL. Это тип с атрибутом `non_exhaustive`, поэтому мы создаём его с помощью `Config::default()`, а затем изменяем нужные параметры. В нашем приложении мы используем `with_cpu_clock(CpuClock::max())`, чтобы запросить максимальную тактовую частоту ЦП:
```rust,ignore
{{#shiftinclude auto:../../project/part1/src/main.rs:esp_hal_init}}
@@ -62,7 +62,7 @@ ESP_LOG=warn,no_std_training=info cargo run --release
[`esp_hal::init`][esp-hal-init] применяет эту конфигурацию. Он настраивает тактовую частоту ЦП и сторожевой таймер (watchdog), а затем возвращает периферию и тактовые сигналы, необходимые HAL.
-Значение, важное для следующих шагов, — `peripherals`. Оно содержит отдельное значение Rust для каждого аппаратного блока и каждого вывода. Когда мы позже создадим драйверы, мы передадим эти значения в конструкторы драйверов. Передача владения и есть то, что позволяет `esp-hal` предотвращать случайное двойное использование оборудования: как только `peripherals.I2C0` будет передан в драйвер I2C (см. ниже), никакой другой драйвер не сможет использовать тот же блок I2C.
+Значение, важное для следующих шагов, — `peripherals`. Оно содержит отдельное значение Rust для каждого аппаратного блока и каждого вывода. Когда мы позже создадим драйверы, мы передадим эти значения в конструкторы драйверов. Именно передача владения позволяет `esp-hal` предотвращать случайное двойное использование оборудования: как только `peripherals.I2C0` будет передан в драйвер I2C (см. ниже), никакой другой драйвер не сможет использовать тот же блок I2C.
### `esp_rtos::start`
diff --git a/no-std-training/training-ru/application/wifi-connectivity.md b/no-std-training/training-ru/application/wifi-connectivity.md
index cf150e7..0b0019a 100644
--- a/no-std-training/training-ru/application/wifi-connectivity.md
+++ b/no-std-training/training-ru/application/wifi-connectivity.md
@@ -18,7 +18,7 @@
{{#include ../../project/part2/src/sensor.rs:read_sensor}}
```
-- `network.rs` содержит две фоновые задачи, которые поддерживают подключение Wi-Fi-радиомодуля и работу IP-стека.
+- `network.rs` содержит две фоновые задачи, которые поддерживают соединение по Wi-Fi и работу IP-стека.
- `http.rs` формирует JSON-нагрузку и отправляет её с помощью минимального HTTP-запроса `POST`.
- `main.rs` по-прежнему инициализирует аппаратное обеспечение, запускает сетевой стек и выполняет основной цикл приложения.
@@ -73,9 +73,9 @@ Wi-Fi устроен иначе. [`esp-radio`][esp-radio] — обёртка н
### Конфигурация `embassy-net`
-`embassy-net` настраивается в двух местах: через фичи Cargo и через значение `Config`, которое мы передаём во время выполнения.
+`embassy-net` настраивается в двух местах: через feature-флаги Cargo и через значение `Config`, которое мы передаём во время выполнения.
-Фичи крейта выбирают, какие протоколы будут скомпилированы:
+Feature-флаги крейта определяют, какие протоколы будут скомпилированы:
```toml
{{#include ../../project/part2/Cargo.toml:embassy_net}}
@@ -86,7 +86,7 @@ Wi-Fi устроен иначе. [`esp-radio`][esp-radio] — обёртка н
- `udp` используется DHCP и DNS.
- `tcp` и `dns` понадобятся позже, когда мы откроем сокет и разрешим имя хоста.
-Также включаем поддержку Embassy в `esp-rtos` и фичу `wifi` в `esp-radio`:
+Также включаем поддержку Embassy в `esp-rtos` и feature `wifi` в `esp-radio`:
```toml
{{#include ../../project/part2/Cargo.toml:esp_radio}}
@@ -108,13 +108,13 @@ Wi-Fi устроен иначе. [`esp-radio`][esp-radio] — обёртка н
### Почему ресурсы стека статические
-[`embassy_net::new`][embassy-net-new] требует драйвер Wi-Fi, конфигурацию, случайное зерно и буфер [`StackResources`][stack-resources]. `N` — количество сокетов, которые стек может держать открытыми одновременно. Мы используем `3`: этого хватает для DHCP, DNS и одного TCP-соединения.
+[`embassy_net::new`][embassy-net-new] требует драйвер Wi-Fi, конфигурацию, начальное случайное значение (seed) и буфер [`StackResources`][stack-resources]. `N` — количество сокетов, которые стек может держать открытыми одновременно. Мы используем `3`: этого хватает для DHCP, DNS и одного TCP-соединения.
```rust,ignore
{{#shiftinclude auto:../../project/part2/src/main.rs:stack_init}}
```
-Эти ресурсы, `Runner` и запускаемые задачи требуют времени жизни `'static`. Задачи Embassy не могут заимствовать данные из стека `main`: после запуска задача может работать до конца программы, поэтому все её аргументы должны жить дольше, чем `main`.
+Эти ресурсы, `Runner` и запускаемые задачи должны иметь время жизни `'static`. Задачи Embassy не могут заимствовать данные из стека `main`: после запуска задача может работать до конца программы, поэтому все её аргументы должны жить дольше, чем `main`.
Обычный локальный `let resources = StackResources::new();` был бы уничтожен при выходе из `main` (хотя этого никогда не происходит, система типов не может этим воспользоваться), и его нельзя было бы передать задаче `'static`. `static mut` скомпилировался бы только с `unsafe`.
diff --git a/no-std-training/training-ru/application/wifi-provisioning.md b/no-std-training/training-ru/application/wifi-provisioning.md
index 1d66959..7bdf8ee 100644
--- a/no-std-training/training-ru/application/wifi-provisioning.md
+++ b/no-std-training/training-ru/application/wifi-provisioning.md
@@ -199,7 +199,7 @@ HTTP-сервер получает учётные данные, но `WifiContro
{{#include ../../project/part4/src/network.rs:wifi_credentials}}
```
-Поля — строки [`heapless::String`][heapless-string] фиксированной ёмкости, размер которых соответствует ограничениям Wi-Fi: SSID — не более 32 байт, а парольная фраза WPA2 — не более 63 символов или 64 шестнадцатеричных цифр. Деривация `Deserialize` позволяет обработчику HTTP создать структуру напрямую из тела JSON-запроса. Фича `serde` в `heapless` делает это возможным.
+Поля — строки [`heapless::String`][heapless-string] фиксированной ёмкости, размер которых соответствует ограничениям Wi-Fi: SSID — не более 32 байт, а парольная фраза WPA2 — не более 63 символов или 64 шестнадцатеричных цифр. Реализация `Deserialize` через `derive` позволяет обработчику HTTP создать структуру напрямую из тела JSON-запроса. Это возможно благодаря feature `serde` в `heapless`.
Задача `connection` ожидает на приёмном конце:
@@ -311,7 +311,7 @@ Topic: measurement/humidity | Payload: 42.18
Этот пример показывает основу Wi-Fi-провизионинга, но не включает несколько вещей, которые понадобились бы продукту:
- **Учётные данные не сохраняются.** Они существуют только в RAM, поэтому после каждого сброса портал провизионинга запускается заново. Реальное устройство сохраняло бы их во флеш-памяти и запускало портал, только если сохранённых действительных учётных данных нет.
-- **Точка доступа открыта.** Любой поблизости может подключиться к ней и отправить учётные данные, а пароль передаётся по обычному HTTP. Защитить точку доступа паролем WPA2 или использовать протокол провизионинга с собственным шифрованием, например схемы безопасности из компонента provisioning в ESP-IDF, — способы решить эту проблему.
+- **Точка доступа открыта.** Любой поблизости может подключиться к ней и отправить учётные данные, а пароль передаётся по обычному HTTP. Решить эту проблему можно, защитив точку доступа паролем WPA2 или применив протокол провизионинга с собственным шифрованием, например схемы безопасности из компонента provisioning в ESP-IDF.
- **Нет обратной связи при ошибке.** Точка доступа уже пропадает к моменту, когда устройство пробует учётные данные, поэтому пользователь не видит на странице сообщение об ошибке подключения.
На этом этапе устройству больше не нужны учётные данные на этапе компиляции: одна и та же прошивка может подключиться к любой сети. В следующей главе мы рассмотрим обновление прошивки в полевых условиях с помощью [обновлений по воздуху (OTA)](./ota-updates.md).
diff --git a/no-std-training/training-ru/introduction.md b/no-std-training/training-ru/introduction.md
index 68b4429..179c087 100644
--- a/no-std-training/training-ru/introduction.md
+++ b/no-std-training/training-ru/introduction.md
@@ -8,7 +8,7 @@
Цель этой книги — дать подробное руководство по началу работы с языком программирования Rust на устройствах ESP32-C3 от Espressif.
-Книга проведёт вас через создание приложения на Rust с `no_std` с использованием [esp-hal]. По ходу дела мы будем использовать различную аппаратную периферию. Подробнее о приложении, которое мы будем создавать, рассказано в главе [Обзор проекта].
+Книга проведёт вас через создание приложения на Rust в режиме `no_std` с использованием [esp-hal]. По ходу дела мы будем работать с разной аппаратной периферией. Подробнее о приложении, которое мы будем создавать, рассказано в главе [Обзор проекта].
Мы предполагаем, что вы уже знакомы с Rust; подробности см. в главе [Предварительные требования].
@@ -23,9 +23,9 @@
Эта книга рассчитана на чтение от начала до конца. Последующие главы опираются на понятия, введённые в предыдущих главах, а ранние главы могут опускать детали, которые раскрываются позже.
-Исходный код приложения, которое мы будем создавать, находится в репозитории [`esp-rs/no_std-training`].
+Исходный код приложения, которое мы будем создавать, находится в каталоге [`no-std-training/project`] этого репозитория.
-[`esp-rs/no_std-training`]: https://github.com/r007/EmbeddedRust-Rus/tree/main/no-std-training/tree/main
+[`no-std-training/project`]: https://github.com/r007/EmbeddedRust-Rus/tree/main/no-std-training/project
## Принятые в книге обозначения
diff --git a/no-std-training/training-ru/prerequisites.md b/no-std-training/training-ru/prerequisites.md
index c5c8111..1963f1c 100644
--- a/no-std-training/training-ru/prerequisites.md
+++ b/no-std-training/training-ru/prerequisites.md
@@ -4,14 +4,14 @@
## Rust
-Требуется определённый опыт работы с Rust и программирования в целом. Этот курс не ставит целью научить программированию или языку Rust в целом, поскольку для этих тем уже существует много качественных материалов.
+Требуется определённый опыт работы с Rust и программирования в целом. Этот курс не ставит целью научить программированию или самому языку Rust, поскольку для этих тем уже существует много качественных материалов.
Если вы совсем не знакомы с языком, мы рекомендуем сначала прочитать [The Rust Book] (на английском языке). Также можно заранее ознакомиться с [The Rust on ESP Book], хотя это и не обязательно.
[the rust book]: https://doc.rust-lang.org/book/
[the rust on esp book]: https://esp-rs.github.io/book/
-### Инструментарий
+### Тулчейн
Требуется последняя стабильная версия тулчейна Rust, а также нужно установить целевую платформу `riscv32imc-unknown-none-elf`.
@@ -35,7 +35,7 @@ cargo install espflash --locked
В этом курсе мы будем использовать отладочную плату [ESP32-C3-DevKit-RUST-2]. Можно использовать и другие платы, но эта плата содержит датчики и другие устройства, которые используются нашим приложением, поэтому для наилучших результатов настоятельно рекомендуется использовать именно её.
-Исходные файлы этой отладочной платы доступны в репозитории [esp-rs/esp-rust-board]. Плату можно купить на AliExpress и Mouser, см. раздел [Где купить].
+Проектные файлы этой отладочной платы (схемы и т. п.) доступны в репозитории [esp-rs/esp-rust-board]. Плату можно купить на AliExpress и Mouser, см. раздел [Где купить].
[esp32-c3-devkit-rust-2]: https://github.com/esp-rs/esp-rust-board
[esp-rs/esp-rust-board]: https://github.com/esp-rs/esp-rust-board
diff --git a/pico-pico/src/SUMMARY.md b/pico-pico/src/SUMMARY.md
index 02abfb2..9b32a48 100644
--- a/pico-pico/src/SUMMARY.md
+++ b/pico-pico/src/SUMMARY.md
@@ -47,18 +47,18 @@
- [Сервопривод](./servo/index.md)
- [Как это работает](./servo/how-servo-works.md)
- [Схема подключения](./servo/connect-with-pico.md)
- - [Положение и скважность](./servo/servo-pico.md)
+ - [Положение и коэффициент заполнения](./servo/servo-pico.md)
- [Код](./servo/code-using-embassy-rp.md)
- [С использованием rp-hal](./servo/code-using-rp-hal.md)
- [Buzzinga](./buzzer/intro.md)
- [Схема подключения](./buzzer/circuit.md)
- [Пищание](./buzzer/beep.md)
- - [GOT-зуммер?](./buzzer/play-songs/index.md)
+ - [GOT-пищалка?](./buzzer/play-songs/index.md)
- [Музыкальные ноты](./buzzer/play-songs/music-theory.md)
- [Модуль музыки](./buzzer/play-songs/music-module.md)
- [Модуль песни](./buzzer/play-songs/song-module.md)
- [Код](./buzzer/play-songs/code.md)
- - [Активный зуммер](./buzzer/active-beep.md)
+ - [Активная пищалка](./buzzer/active-beep.md)
- [Делитель напряжения](./core-concepts/voltage-divider.md)
- [Ультразвуковой датчик](./ultrasonic/index.md)
- [Как это работает?](./ultrasonic/how-it-works.md)
@@ -112,7 +112,7 @@
- [Из АЦП в сопротивление](./thermistor/adc-to-resistance.md)
- [Нелинейность](./thermistor/non-linear.md)
- [Уравнение B](./thermistor/b-equation.md)
- - [Уравнение Штайнхарта — Харта](./thermistor/steinhart.md)
+ - [Уравнение Стейнхарта — Харта](./thermistor/steinhart.md)
- [Температура на OLED](./thermistor/temperature/index.md)
- [Код](./thermistor/temperature/code.md)
- [USB Serial](./usb-serial/index.md)
diff --git a/pico-pico/src/abstraction-layers.md b/pico-pico/src/abstraction-layers.md
index c712e4f..2e26931 100644
--- a/pico-pico/src/abstraction-layers.md
+++ b/pico-pico/src/abstraction-layers.md
@@ -8,13 +8,13 @@
-## Пакет поддержки платы (BSP)
+## Крейт поддержки платы (BSP)
-BSP, в Rust также называемый Board Support Crate, — это пакет, созданный под конкретные отладочные платы. Он объединяет HAL с настройками, специфичными для платы, и предоставляет готовые интерфейсы для встроенных компонентов, таких как светодиоды, кнопки и датчики. Это позволяет разработчикам сосредоточиться на логике приложения, а не на низкоуровневых деталях оборудования. Поскольку популярного BSP именно для Raspberry Pi Pico 2 нет, в этой книге мы не будем использовать этот подход.
+BSP, в Rust также называемый Board Support Crate, — это крейт, созданный под конкретные отладочные платы. Он объединяет HAL с настройками, специфичными для платы, и предоставляет готовые интерфейсы для встроенных компонентов, таких как светодиоды, кнопки и датчики. Это позволяет разработчикам сосредоточиться на логике приложения, а не на низкоуровневых деталях оборудования. Поскольку популярного BSP именно для Raspberry Pi Pico 2 нет, в этой книге мы не будем использовать этот подход.
---
-## Уровень абстракции оборудования (HAL)
+## Слой аппаратной абстракции (HAL)
HAL находится непосредственно под уровнем BSP. Если вы работаете с платами Raspberry Pi Pico или платами на базе ESP32, в основном вы будете использовать именно HAL. HAL обычно пишут под конкретный чип (например, RP2350 или ESP32), а не под отдельные платы, поэтому один и тот же HAL подходит для разных плат с одним и тем же микроконтроллером. Для семейства микроконтроллеров Raspberry Pi существует крейт [rp-hal](https://github.com/rp-rs/rp-hal), который предоставляет эту абстракцию.
@@ -24,7 +24,7 @@ HAL для микроконтроллеров обычно реализуют т
### Embassy для RP
-Embassy находится на том же уровне, что и HAL, но дополнительно предоставляет среду выполнения с поддержкой асинхронности. Embassy (а точнее, embassy-rp для Raspberry Pi Pico) построен поверх уровня HAL и предоставляет асинхронный исполнитель, таймеры и дополнительные абстракции, которые упрощают написание параллельных embedded-приложений.
+Embassy находится на том же уровне, что и HAL, но дополнительно предоставляет среду выполнения с поддержкой асинхронности. Embassy (а точнее, embassy-rp для Raspberry Pi Pico) построен поверх уровня HAL и предоставляет асинхронный исполнитель, таймеры и дополнительные абстракции, которые упрощают написание конкурентных embedded-приложений.
Embassy предоставляет отдельный крейт `embassy-rp` для микроконтроллеров Raspberry Pi (RP2040 и RP235x). Этот крейт напрямую опирается на rp-pac (Raspberry Pi Peripheral Access Crate).
diff --git a/pico-pico/src/additional-hardware.md b/pico-pico/src/additional-hardware.md
index 7cd3e38..19c930d 100644
--- a/pico-pico/src/additional-hardware.md
+++ b/pico-pico/src/additional-hardware.md
@@ -13,7 +13,7 @@
Базовый набор для электроники
-Другие компоненты, которые используются в книге: светодиоды, ультразвуковой датчик HC-SR04, активные и пассивные зуммеры, микросервопривод SG90, фоторезистор LDR, NTC-термистор, RFID-считыватель RC522, адаптер для micro SD-карты, дисплей HD44780 и модуль джойстика.
+Другие компоненты, которые используются в книге: светодиоды, ультразвуковой датчик HC-SR04, активные и пассивные пищалки, микросервопривод SG90, фоторезистор LDR, NTC-термистор, RFID-считыватель RC522, адаптер для micro SD-карты, дисплей HD44780 и модуль джойстика.
## Дополнительное оборудование: отладочный зонд
@@ -26,6 +26,6 @@
Отладочный зонд Raspberry Pi Pico
-### Как решить?
+### Стоит ли покупать?
Если бюджет ограничен, можно пока обойтись без него: зонд стоит примерно вдвое дороже Pico 2. Если цена не главный фактор, это хорошая покупка, которая очень пригодится. Также можно использовать другую Pico как недорогой отладочный зонд, если у вас есть вторая плата.
diff --git a/pico-pico/src/async-embedded-rust/introduction.md b/pico-pico/src/async-embedded-rust/introduction.md
index f3d9b46..794f4ae 100644
--- a/pico-pico/src/async-embedded-rust/introduction.md
+++ b/pico-pico/src/async-embedded-rust/introduction.md
@@ -8,7 +8,7 @@
Если вы знакомы с концепциями параллелизма и асинхронности, эта аналогия вам не нужна: Embassy, по сути, похож на Tokio для встраиваемых систем и предоставляет асинхронную среду выполнения. Если же вы только начинаете знакомиться с асинхронностью, объясню на примере.
-Вы готовите ужин и ставите воду кипятиться. Вместо того чтобы стоять и смотреть на кастрюлю, вы режете овощи. Время от времени вы поглядываете на кастрюлю, и, когда появляются пузырьки, вы готовы к следующему шагу. Пока основное блюдо готовится, вы в другой сковороде делаете гарнир. Вы даже проверяете сообщение на телефоне. Вы — один человек, который постоянно переключается между задачами, отслеживает, что требует внимания, делает работу, как только что-то готово, и никогда не стоит без дела, ожидая.
+Вы готовите ужин и ставите воду кипятиться. Вместо того чтобы стоять и смотреть на кастрюлю, вы режете овощи. Время от времени вы поглядываете на кастрюлю, и, когда появляются пузырьки, вы готовы к следующему шагу. Пока основное блюдо готовится, вы на другой сковороде делаете гарнир. Вы даже проверяете сообщение на телефоне. Вы — один человек, который постоянно переключается между задачами, отслеживает, что требует внимания, делает работу, как только что-то готово, и никогда не стоит без дела, ожидая.
diff --git a/pico-pico/src/buzzer/active-beep.md b/pico-pico/src/buzzer/active-beep.md
index 7bbad85..a8c74ba 100644
--- a/pico-pico/src/buzzer/active-beep.md
+++ b/pico-pico/src/buzzer/active-beep.md
@@ -1,15 +1,15 @@
-{{#title Пищание активным зуммером на Raspberry Pi Pico 2 на embedded Rust}}
+{{#title Писк активной пищалки на Raspberry Pi Pico 2 на embedded Rust}}
-# Пищание активным зуммером
+# Писк активной пищалки
-Поскольку вы уже знаете, как работает активный зуммер, заставить его пищать можно просто включая и выключая вывод GPIO. В этом упражнении мы подаём питание на зуммер через вывод GPIO, ждём короткое время, выключаем и повторяем. Так получается отчётливый звуковой сигнал.
+Поскольку вы уже знаете, как работает активная пищалка, заставить её пищать можно просто включая и выключая вывод GPIO. В этом упражнении мы подаём питание на пищалку через вывод GPIO, ждём короткое время, выключаем и повторяем. Так получается отчётливый звуковой сигнал.
> [!Note]
-> Этот пример предназначен для активного зуммера. Если использовать пассивный, звук может быть странным или нестабильным. Выполняйте это упражнение только с активным зуммером.
+> Этот пример предназначен для активной пищалки. Если использовать пассивную, звук может быть странным или нестабильным. Выполняйте это упражнение только с активной пищалкой.
### Требования к оборудованию
-- Активный зуммер
+- Активная пищалка
- Перемычки (female-to-male или male-to-male, в зависимости от вашей схемы)
## Проект из шаблона
@@ -24,7 +24,7 @@ cargo generate --git https://github.com/ImplFerris/pico2-template.git --tag v0.3
## Основная логика
-Убедитесь, что зуммер подключён к GPIO 15. Вывод переключается каждые 500 миллисекунд, чтобы включать и выключать зуммер.
+Убедитесь, что пищалка подключена к GPIO 15. Вывод переключается каждые 500 миллисекунд, чтобы включать и выключать пищалку.
```rust
let mut buzzer = Output::new(p.PIN_15, Level::Low);
diff --git a/pico-pico/src/buzzer/beep.md b/pico-pico/src/buzzer/beep.md
index 36146c8..f995ba1 100644
--- a/pico-pico/src/buzzer/beep.md
+++ b/pico-pico/src/buzzer/beep.md
@@ -1,10 +1,10 @@
-# Сигнал зуммера с помощью ШИМ на Raspberry Pi Pico на embedded Rust
+# Сигнал пищалки с помощью ШИМ на Raspberry Pi Pico на embedded Rust
-В этом упражнении мы сгенерируем звуковой сигнал с помощью зуммера. Идея похожа на мигание светодиодом, но вместо того, чтобы переключать вывод GPIO между HIGH и LOW, мы управляем скважностью ШИМ.
+В этом упражнении мы сгенерируем звуковой сигнал с помощью пищалки. Идея похожа на мигание светодиодом, но вместо того, чтобы переключать вывод GPIO между HIGH и LOW, мы управляем коэффициентом заполнения ШИМ.
-Будем многократно переключать скважность ШИМ между 50 процентами и 0 процентами с задержкой между переключениями. Когда скважность составляет 50 процентов, зуммер издаёт звук. Когда 0 процентов — звук прекращается. Повторение этого создаёт отчётливый сигнал.
+Будем многократно переключать коэффициент заполнения ШИМ между 50 процентами и 0 процентами с задержкой между переключениями. Когда коэффициент заполнения составляет 50 процентов, пищалка издаёт звук. Когда 0 процентов — звук прекращается. Повторение этого создаёт отчётливый сигнал.
-Можно попробовать и без изменения частоты ШИМ. В этом примере мы задаём частоту ШИМ 440,0 Гц. Это соответствует музыкальной ноте `a4` (ля первой октавы) и тональному сигналу телефонии (call progress tone), который используется в Северной Америке и большей части Европы. Знать что-либо о нотах для этого не нужно. Важно лишь то, что мы генерируем тон фиксированной частоты и включаем или выключаем звук, меняя скважность.
+Можно попробовать и без изменения частоты ШИМ. В этом примере мы задаём частоту ШИМ 440,0 Гц. Это соответствует музыкальной ноте `a4` (ля первой октавы) и тональному сигналу телефонии (call progress tone), который используется в Северной Америке и большей части Европы. Знать что-либо о нотах для этого не нужно. Важно лишь то, что мы генерируем тон фиксированной частоты и включаем или выключаем звук, меняя коэффициент заполнения.
## Создание проекта из шаблона
@@ -51,7 +51,7 @@ const PWM_TOP: u16 = get_top(440., PWM_DIV_INT);
## Основная логика
-Сначала настраиваем ШИМ с вычисленным значением TOP и фиксированным делителем. Затем создаём выход ШИМ для зуммера. Внутри цикла переключаем скважность между 50 процентами и 0 процентами с задержкой между переключениями, что даёт повторяющийся звуковой сигнал.
+Сначала настраиваем ШИМ с вычисленным значением TOP и фиксированным делителем. Затем создаём выход ШИМ для пищалки. Внутри цикла переключаем коэффициент заполнения между 50 процентами и 0 процентами с задержкой между переключениями, что даёт повторяющийся звуковой сигнал.
```rust
let mut pwm_config = PwmConfig::default();
diff --git a/pico-pico/src/buzzer/circuit.md b/pico-pico/src/buzzer/circuit.md
index 29b5ed1..d202a70 100644
--- a/pico-pico/src/buzzer/circuit.md
+++ b/pico-pico/src/buzzer/circuit.md
@@ -1,14 +1,14 @@
-# Подключение зуммера к Raspberry Pi Pico
+# Подключение пищалки к Raspberry Pi Pico
-Подключим GPIO 15 к положительному (сигнальному) выводу зуммера, а GND Pico — к земляному выводу зуммера. При необходимости можно использовать другой вывод GPIO.
+Подключим GPIO 15 к положительному (сигнальному) выводу пищалки, а GND Pico — к земляному выводу пищалки. При необходимости можно использовать другой вывод GPIO.
Вывод Pico
Провод
-
Вывод зуммера
+
Вывод пищалки
Примечания
@@ -38,4 +38,4 @@
-
+
diff --git a/pico-pico/src/buzzer/intro.md b/pico-pico/src/buzzer/intro.md
index a4b1a89..857d0b4 100644
--- a/pico-pico/src/buzzer/intro.md
+++ b/pico-pico/src/buzzer/intro.md
@@ -1,56 +1,56 @@
-{{#title Основы зуммера для Raspberry Pi Pico 2 | impl Rust для RP2350}}
+{{#title Основы работы с пищалкой для Raspberry Pi Pico 2 | impl Rust для RP2350}}
# Buzzinga
-В этом разделе мы рассмотрим несколько интересных занятий с использованием зуммера. Название Buzzinga я выбрал просто ради шутки (это игра слов с «Bazinga» — фразой Шелдона из сериала «Теория большого взрыва»). Это не технический термин.
+В этом разделе мы рассмотрим несколько интересных занятий с использованием пищалки. Название Buzzinga я выбрал просто ради шутки (это игра слов с «Bazinga» — фразой Шелдона из сериала «Теория большого взрыва»). Это не технический термин.
-## Что такое зуммер?
+## Что такое пищалка?
-Зуммер — небольшой электронный компонент, который издаёт звук, когда на него подают питание или управляющий электрический сигнал. Его используют для генерации сигналов, оповещений или простых мелодий, обеспечивая звуковую обратную связь в электронных устройствах.
+Пищалка (зуммер) — небольшой электронный компонент, который издаёт звук, когда на него подают питание или управляющий электрический сигнал. Её используют для генерации сигналов, оповещений или простых мелодий, обеспечивая звуковую обратную связь в электронных устройствах.
-Зуммеры часто встречаются в будильниках, таймерах, системах уведомлений, компьютерах и простых пользовательских интерфейсах, где они подтверждают действия пользователя или сигнализируют о событиях.
+Пищалки часто встречаются в будильниках, таймерах, системах уведомлений, компьютерах и простых пользовательских интерфейсах, где они подтверждают действия пользователя или сигнализируют о событиях.
-## Распространённые типы зуммеров
+## Распространённые типы пищалок
В embedded-проектах вы чаще всего будете встречать два типа:
-### Активный зуммер
+### Активная пищалка
-Внутри такого зуммера есть встроенный генератор. Нужно только подать питание, и он сразу начнёт издавать звук. Активные зуммеры очень просты в использовании, но позволяют мало управлять высотой тона.
+Внутри такой пищалки есть встроенный генератор. Нужно только подать питание, и она сразу начнёт издавать звук. Активные пищалки очень просты в использовании, но позволяют мало управлять высотой тона.
-
+
#### Как определить
-Активный зуммер обычно имеет белое покрытие сверху и гладкий чёрный корпус снизу. Проще всего его проверить, подключив напрямую к батарейке: если он издаёт звук без дополнительных схем, это активный зуммер.
+Активная пищалка обычно имеет белое покрытие сверху и гладкий чёрный корпус снизу. Проще всего проверить её, подключив напрямую к батарейке: если она издаёт звук без дополнительных схем, это активная пищалка.
-### Пассивный зуммер
+### Пассивная пищалка
-Пассивный зуммер сам по себе звука не издаёт. Его нужно управлять сигналом ШИМ или меандром (прямоугольными импульсами). Это позволяет задавать частоту, а значит, получать разные тона или даже простые мелодии.
+Пассивная пищалка сама по себе звука не издаёт. Ею нужно управлять сигналом ШИМ или меандром (прямоугольными импульсами). Это позволяет задавать частоту, а значит, получать разные тона или даже простые мелодии.
-
+
#### Как определить
-У пассивного зуммера обычно нет белого покрытия сверху, и часто он выглядит как маленькая печатная плата с синим или зелёным основанием. Если подключить его напрямую к батарейке, звука не будет.
+У пассивной пищалки обычно нет белого покрытия сверху, и часто она выглядит как маленькая печатная плата с синим или зелёным основанием. Если подключить её напрямую к батарейке, звука не будет.
## Какой выбрать?
-Выбирайте активный зуммер, если нужен простой фиксированный тон или сигнал. Он подходит для базовых оповещений, будильников или подтверждения действий пользователя и требует минимальной настройки.
+Выбирайте активную пищалку, если нужен простой фиксированный тон или сигнал. Он подходит для базовых оповещений, будильников или подтверждения действий пользователя и требует минимальной настройки.
-Выбирайте пассивный зуммер, если хотите больше контроля над звуком. Поскольку им нужно управлять сигналом ШИМ или меандром, можно получать разные тоны, мелодии и звуковые узоры.
+Выбирайте пассивную пищалку, если хотите больше контроля над звуком. Поскольку ею управляют сигналом ШИМ или меандром, можно получать разные тоны, мелодии и звуковые узоры.
-Для наших упражнений рекомендуется пассивный зуммер, потому что он позволяет напрямую задавать частоту выходного сигнала и получить более качественный тон. Однако если у вас есть только активный зуммер, можно всё равно следовать книге. Я сам сначала использовал именно активный.
+Для наших упражнений рекомендуется пассивная пищалка, потому что она позволяет напрямую задавать частоту выходного сигнала и получить более качественный тон. Однако если у вас есть только активная пищалка, можно всё равно следовать книге. Я сам сначала использовал именно активную.
## Требования к оборудованию
-- Пассивный зуммер
+- Пассивная пищалка
- Перемычки
-У зуммера обычно два вывода: положительный (для сигнала) и земляной. Положительный вывод часто помечен знаком «+» и, как правило, длиннее, а отрицательный — короче, как у светодиода.
+У пищалки обычно два вывода: положительный (для сигнала) и земляной. Положительный вывод часто помечен знаком «+» и, как правило, длиннее, а отрицательный — короче, как у светодиода.
-Однако некоторые пассивные зуммеры не имеют полярности. В этом случае любой из выводов можно подключить к сигналу или к земле. Если не уверены, проверьте маркировку или даташит.
+Однако некоторые пассивные пищалки не имеют полярности. В этом случае любой из выводов можно подключить к сигналу или к земле. Если не уверены, проверьте маркировку или даташит.
## Ссылка
-- [Официальное руководство Raspberry Pi по зуммеру](https://projects.raspberrypi.org/en/projects/introduction-to-the-pico/9)
+- [Официальное руководство Raspberry Pi по пищалке](https://projects.raspberrypi.org/en/projects/introduction-to-the-pico/9)
diff --git a/pico-pico/src/buzzer/play-songs/code.md b/pico-pico/src/buzzer/play-songs/code.md
index 67117d9..433588d 100644
--- a/pico-pico/src/buzzer/play-songs/code.md
+++ b/pico-pico/src/buzzer/play-songs/code.md
@@ -15,7 +15,7 @@ use embassy_rp::pwm::{Config as PwmConfig, Pwm, SetDutyCycle};
use crate::music::Song;
```
-## ШИМ и зуммер
+## ШИМ и пищалка
В отличие от предыдущего примера, мы клонируем `PwmConfig`. Конструктор `Pwm` забирает объект конфигурации, а внутри цикла нам нужно менять `top`, чтобы задавать частоту ШИМ для каждой музыкальной ноты.
@@ -51,7 +51,7 @@ for (note, duration_type) in got::MELODY {
buzzer
.set_duty_cycle_percent(50)
- .expect("50 is valid duty percentage"); // Ставим скважность 50%, чтобы сыграть ноту
+ .expect("50 is valid duty percentage"); // Ставим коэффициент заполнения 50%, чтобы сыграть ноту
Timer::after_millis(note_duration - pause_duration).await; // Играем 90%
@@ -62,11 +62,11 @@ for (note, duration_type) in got::MELODY {
}
```
-Для каждой ноты частота ШИМ обновляется установкой нового значения `top`. Это заставляет зуммер издавать нужную высоту тона.
+Для каждой ноты частота ШИМ обновляется установкой нового значения `top`. Это заставляет пищалку издавать нужную высоту тона.
Длительность ноты рассчитывается по темпу песни. Большую часть времени нота звучит, а небольшая часть остаётся тихой. Эта короткая тишина помогает отделить ноты друг от друга, благодаря чему мелодия звучит чище.
-Зуммер включается установкой скважности 50 процентов и выключается установкой нуля.
+Пищалка включается установкой коэффициента заполнения 50 процентов и выключается установкой нуля.
### Поддержание работы программы
diff --git a/pico-pico/src/buzzer/play-songs/index.md b/pico-pico/src/buzzer/play-songs/index.md
index 68be3be..61ef813 100644
--- a/pico-pico/src/buzzer/play-songs/index.md
+++ b/pico-pico/src/buzzer/play-songs/index.md
@@ -1,8 +1,8 @@
-{{#title Воспроизведение музыки на Raspberry Pi Pico 2 с пассивным зуммером на embedded Rust}}
+{{#title Воспроизведение музыки на Raspberry Pi Pico 2 с пассивной пищалкой на embedded Rust}}
-# Воспроизведение песен на пассивном зуммере с помощью Rust и Raspberry Pi Pico
+# Воспроизведение песен на пассивной пищалке с помощью Rust и Raspberry Pi Pico
-В этом разделе мы будем воспроизводить песни на зуммере с помощью Raspberry Pi Pico.
+В этом разделе мы будем воспроизводить песни на пищалке с помощью Raspberry Pi Pico.
Если вы не знакомы с нотами и нотным письмом, можно посмотреть [краткую теорию](./music-theory.md). Эта часть необязательна и нужна лишь для того, чтобы дать базовые сведения, необходимые для понимания примера.
@@ -11,11 +11,11 @@
- [`music`](./music-module.md)
- [`got`](./song-module.md)
-Для этого упражнения рекомендуется пассивный зуммер, хотя подойдёт и пассивный, и активный.
+Для этого упражнения рекомендуется пассивная пищалка, хотя подойдёт любая.
## ШИМ
-Мы используем ШИМ, чтобы управлять частотой сигнала, отправляемого на зуммер. Каждая частота соответствует музыкальной ноте. Частота (нота) удерживается заданное время, а затем происходит переход к следующей ноте согласно музыкальным данным.
+Мы используем ШИМ, чтобы управлять частотой сигнала, отправляемого на пищалку. Каждая частота соответствует музыкальной ноте. Частота (нота) удерживается заданное время, а затем происходит переход к следующей ноте согласно музыкальным данным.
Например, нота `a4` — это 440 Гц. Чтобы её сыграть, мы настраиваем выход ШИМ на 440 Гц и держим его включённым нужное время, прежде чем перейти к следующей ноте.
@@ -23,7 +23,7 @@
## Репозиторий песен
-В этом упражнении в качестве демонстрации мы сыграем на зуммере музыкальную тему.
+В этом упражнении в качестве демонстрации мы сыграем на пищалке музыкальную тему.
Также можно посмотреть репозиторий `rust-embedded-songs` и попробовать другие песни:
diff --git a/pico-pico/src/buzzer/play-songs/music-module.md b/pico-pico/src/buzzer/play-songs/music-module.md
index c38c94a..f50e6eb 100644
--- a/pico-pico/src/buzzer/play-songs/music-module.md
+++ b/pico-pico/src/buzzer/play-songs/music-module.md
@@ -108,7 +108,7 @@ pub struct Song {
}
```
-Поле whole_note хранит длительность целой ноты в миллисекундах. Все остальные длительности нот вычисляются из этого значения. Использование миллисекунд упрощает задержки при воспроизведении нот на зуммере.
+Поле whole_note хранит длительность целой ноты в миллисекундах. Все остальные длительности нот вычисляются из этого значения. Использование миллисекунд упрощает задержки при воспроизведении нот на пищалке.
## Создание песни
diff --git a/pico-pico/src/components.md b/pico-pico/src/components.md
index 2da2e29..963008e 100644
--- a/pico-pico/src/components.md
+++ b/pico-pico/src/components.md
@@ -27,7 +27,7 @@
- OLED-дисплей (SSD1306, 128x64, I2C)
- ЖК-дисплей (16x2, совместимый с HD44780)
- Ультразвуковой датчик (HC-SR04 / HC-SR04+)
-- Зуммер (активный и пассивный)
+- Пищалка (активная и пассивная)
- Сервопривод (SG90)
- Модуль светодиодной матрицы 8x8 на MAX7219
- RFID-модуль (RC522)
diff --git a/pico-pico/src/core-concepts/basics/breadboard.md b/pico-pico/src/core-concepts/basics/breadboard.md
index d6b6d5b..d1bb4ce 100644
--- a/pico-pico/src/core-concepts/basics/breadboard.md
+++ b/pico-pico/src/core-concepts/basics/breadboard.md
@@ -26,5 +26,5 @@
Вот несколько простых примеров:
- Если вставить провод в гнездо 5a, а другой — в 5c, они соединены, так как находятся в одном ряду.
-- Если один провод вставить в 5a, а другой — в 5f, они `не` соединены, потому что находятся по разные стороны разрыва.
-- Если один провод вставить в 5a, а другой — в 6a, они `не` соединены, так как находятся в разных рядах.
+- Если один провод вставить в 5a, а другой — в 5f, они **не** соединены, потому что находятся по разные стороны разрыва.
+- Если один провод вставить в 5a, а другой — в 6a, они **не** соединены, так как находятся в разных рядах.
diff --git a/pico-pico/src/core-concepts/pwm/basic-concepts.md b/pico-pico/src/core-concepts/pwm/basic-concepts.md
index 8811168..06d5b59 100644
--- a/pico-pico/src/core-concepts/pwm/basic-concepts.md
+++ b/pico-pico/src/core-concepts/pwm/basic-concepts.md
@@ -12,29 +12,29 @@
В этом примере сигнал половину времени находится на уровне 3,3 В, а половину — на уровне 0 В. Поэтому устройство получает в среднем примерно половину напряжения, то есть около 1,65 В.
-## Ширина импульса и скважность
+## Ширина импульса и коэффициент заполнения
Ширина импульса — это просто то, как долго сигнал остаётся включённым, прежде чем выключиться. Она измеряется во времени, например в микросекундах или миллисекундах.
Например, если импульс имеет ширину 1 миллисекунду, сигнал остаётся в HIGH 1 миллисекунду, а затем переходит в LOW на оставшуюся часть цикла.
-Скважность (duty cycle) описывает ту же идею, но иначе. Вместо времени она показывает, какую часть цикла сигнал остаётся включённым, в процентах.
+Коэффициент заполнения (duty cycle) описывает ту же идею, но иначе. Вместо времени он показывает, какую часть цикла сигнал остаётся включённым, в процентах.
Поэтому вместо того чтобы говорить, что сигнал включён 1 миллисекунду, можно сказать, что он включён 50 % времени.
Например:
-- Скважность 0 % означает, что сигнал всегда LOW (в среднем 0 В).
-- Скважность 50 % означает, что сигнал HIGH и LOW одинаковое время (в среднем 1,65 В в системе на 3,3 В).
-- Скважность 75 % означает, что сигнал HIGH 75 % времени и LOW 25 % времени.
-- Скважность 100 % означает, что сигнал всегда HIGH (3,3 В).
+- Коэффициент заполнения 0 % означает, что сигнал всегда LOW (в среднем 0 В).
+- Коэффициент заполнения 50 % означает, что сигнал HIGH и LOW одинаковое время (в среднем 1,65 В в системе на 3,3 В).
+- Коэффициент заполнения 75 % означает, что сигнал HIGH 75 % времени и LOW 25 % времени.
+- Коэффициент заполнения 100 % означает, что сигнал всегда HIGH (3,3 В).
-Изменение скважности меняет мощность, которая передаётся нагрузке, поэтому на изображении выше светодиод выглядит тусклым, средним по яркости или полностью ярким.
+Изменение коэффициента заполнения меняет мощность, которая передаётся нагрузке, поэтому на изображении выше светодиод выглядит тусклым, средним по яркости или полностью ярким.
## Пример использования 1: уменьшение яркости светодиода
-Светодиод мигает так быстро, что глаз не видит отдельных импульсов включения и выключения, и вы воспринимаете только среднюю яркость. Низкая скважность делает свечение тусклым, более высокая — ярче, хотя светодиод всё время переключается между полным напряжением и нулём. В следующей главе мы сделаем это на практике.
+Светодиод мигает так быстро, что глаз не видит отдельных импульсов включения и выключения, и вы воспринимаете только среднюю яркость. Низкий коэффициент заполнения делает свечение тусклым, более высокий — ярче, хотя светодиод всё время переключается между полным напряжением и нулём. В следующей главе мы сделаем это на практике.
## Пример использования 2: управление сервоприводом
diff --git a/pico-pico/src/core-concepts/pwm/manual-calculate-top-divider.md b/pico-pico/src/core-concepts/pwm/manual-calculate-top-divider.md
index 360c950..3e64642 100644
--- a/pico-pico/src/core-concepts/pwm/manual-calculate-top-divider.md
+++ b/pico-pico/src/core-concepts/pwm/manual-calculate-top-divider.md
@@ -6,7 +6,7 @@
В следующем разделе есть более удобный способ: с помощью кода на Rust или формы-калькулятора можно автоматически вычислить и TOP, и делитель. Однако ручной метод полезен уже сейчас, потому что помогает понять, как тактовая частота, делитель и значение TOP связаны друг с другом.
-Значение TOP должно лежать в диапазоне от 0 до 65534. Хотя TOP хранится в 16-битном беззнаковом регистре, если установить его в 65535, нельзя получить настоящую скважность 100 процентов. Это происходит потому, что для скважности 100 процентов регистр сравнения скважности (CC) должен быть равен TOP + 1, а сам CC также имеет ширину 16 бит. Если держать TOP не выше 65534, значение TOP + 1 всё ещё помещается в регистр CC, и весь диапазон скважности от 0 до 100 процентов представляется корректно.
+Значение TOP должно лежать в диапазоне от 0 до 65534. Хотя TOP хранится в 16-битном беззнаковом регистре, если установить его в 65535, нельзя получить настоящий коэффициент заполнения 100 процентов. Это происходит потому, что для коэффициента заполнения 100 процентов регистр сравнения коэффициента заполнения (CC) должен быть равен TOP + 1, а сам CC также имеет ширину 16 бит. Если держать TOP не выше 65534, значение TOP + 1 всё ещё помещается в регистр CC, и весь диапазон коэффициента заполнения от 0 до 100 процентов представляется корректно.
Чтобы TOP оставался в этих пределах, мы будем выбирать значения делителя, являющиеся степенями двойки, например 8, 16, 32 или 64. Такой подход работает не для каждой возможной частоты. В некоторых случаях понадобятся другие целые значения или даже дробные делители. Чтобы всё было просто, начнём с этого подхода.
diff --git a/pico-pico/src/core-concepts/pwm/period-frequency.md b/pico-pico/src/core-concepts/pwm/period-frequency.md
index c17b9e0..aaa9850 100644
--- a/pico-pico/src/core-concepts/pwm/period-frequency.md
+++ b/pico-pico/src/core-concepts/pwm/period-frequency.md
@@ -1,6 +1,6 @@
# Период и частота
-К этому моменту у вас должно быть базовое представление о ширине импульса и скважности. Далее рассмотрим ещё два важных понятия, которые используются в ШИМ: период и частоту.
+К этому моменту у вас должно быть базовое представление о ширине импульса и коэффициенте заполнения. Далее рассмотрим ещё два важных понятия, которые используются в ШИМ: период и частоту.
Эти два понятия описывают, как часто повторяется сигнал ШИМ.
diff --git a/pico-pico/src/core-concepts/pwm/pwm-in-rp2350.md b/pico-pico/src/core-concepts/pwm/pwm-in-rp2350.md
index f56194c..dee408d 100644
--- a/pico-pico/src/core-concepts/pwm/pwm-in-rp2350.md
+++ b/pico-pico/src/core-concepts/pwm/pwm-in-rp2350.md
@@ -12,7 +12,7 @@
## Канал
-Каждый слайс содержит два выходных канала: **канал A** и **канал B**. Оба канала используют один и тот же счётчик, поэтому работают на одной частоте и синхронизированы. Однако у каждого канала свой регистр сравнения, что позволяет независимо управлять скважностью. Это даёт возможность получить от одного слайса два связанных, но разных сигнала ШИМ.
+Каждый слайс содержит два выходных канала: **канал A** и **канал B**. Оба канала используют один и тот же счётчик, поэтому работают на одной частоте и синхронизированы. Однако у каждого канала свой регистр сравнения, что позволяет независимо управлять коэффициентом заполнения. Это даёт возможность получить от одного слайса два связанных, но разных сигнала ШИМ.
## Соответствие каналов ШИМ выводам GPIO
diff --git a/pico-pico/src/core-concepts/pwm/simulation.md b/pico-pico/src/core-concepts/pwm/simulation.md
index db77f99..32784f7 100644
--- a/pico-pico/src/core-concepts/pwm/simulation.md
+++ b/pico-pico/src/core-concepts/pwm/simulation.md
@@ -1,4 +1,4 @@
-{{#title Симуляция ШИМ: скважность и частота в embedded Rust}}
+{{#title Симуляция ШИМ: коэффициент заполнения и частота в embedded Rust}}
# Симуляция
@@ -72,7 +72,7 @@
}
-Ниже — интерактивная симуляция. Используйте ползунки, чтобы менять скважность и частоту, и наблюдайте, как меняются ширина импульса и яркость светодиода. Верхняя часть прямоугольного сигнала соответствует состоянию «включено» (HIGH), нижняя — «выключено» (LOW). Ширина высокого участка меняется вместе со скважностью.
+Ниже — интерактивная симуляция. Используйте ползунки, чтобы менять коэффициент заполнения и частоту, и наблюдайте, как меняются ширина импульса и яркость светодиода. Верхняя часть прямоугольного сигнала соответствует состоянию «включено» (HIGH), нижняя — «выключено» (LOW). Ширина высокого участка меняется вместе со коэффициентом заполнения.
@@ -82,7 +82,7 @@
-
+
50%
@@ -92,7 +92,7 @@
-Если в симуляции плавно менять скважность от низкой к высокой и обратно, вы заметите, что светодиод как будто меняет яркость.
+Если в симуляции плавно менять коэффициент заполнения от низкого к высокому и обратно, вы заметите, что светодиод как будто меняет яркость.
```
-Чтобы попробовать сайт, можно использовать любой HTTP-сервер, который умеет отдавать локальные файлы. Например, можно использовать `axum`, как в упражнении 5.1.1, а если у вас установлен `npm`, подойдёт, например, `npx http-server`.
+Чтобы попробовать сайт, подойдёт любой HTTP-сервер, который умеет отдавать локальные файлы: например, `axum`, как в упражнении 5.1.1, или, если у вас установлен `npm`, `npx http-server`.
### 5.3.1.C Обрезка изображений
Добавим в нашу библиотеку на Rust функцию `crop_image(bytes: Vec, max_size: u32) -> Vec`, которая будет обрезать изображения. Можно использовать ту же логику, что и в упражнении 5.1.1 (части D и E), чтобы создать `DynamicImage` из входных байтов, обрезать его и экспортировать в WebP. Пометьте функцию атрибутом `#[wasm_bindgen]` и пересоберите библиотеку, чтобы сгенерировать для неё привязки WebAssembly.
-Если посмотреть на сгенерированные JavaScript-привязки, вы увидите, что `Vec` в функции `crop_image` превратился в `Uint8Array`. Нам понадобится написать JavaScript, который читает выбранное пользователем изображение и передаёт его в `crop_image` как `Uint8Array`.
+Если посмотреть на сгенерированные JavaScript-привязки, вы увидите, что `Vec` в функции `crop_image` превратился в `Uint8Array`. Нам нужно написать JavaScript, который читает выбранное пользователем изображение и передаёт его в `crop_image` как `Uint8Array`.
Сначала получим два других входных элемента:
```js
@@ -69,9 +69,9 @@ window.location.href = URL.createObjectURL(new Blob([cropped_bytes]));
Если выбрать некорректный файл, в консоли браузера появится ошибка. Можно добавить более аккуратную обработку ошибок с помощью [try-catch](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/try...catch), а также проверять, что `image.files[0]` существует, перед чтением файла. Было бы неплохо проверить и то, что значение `max_size` разумно.
### 5.3.1.D Использование крейта web-sys (бонус)
-Вместо того чтобы использовать JavaScript для работы с HTML-документом или вручную связывать внешние JavaScript-функции через `#[wasm_bindgen]`, как мы делали с `alert()`, можно использовать крейт [`web-sys`](https://crates.io/crates/web-sys). Он предоставляет привязки к JavaScript Web API, доступным в браузере. Однако большинство этих API нужно включать вручную, по отдельным фичам.
+Вместо того чтобы использовать JavaScript для работы с HTML-документом или вручную связывать внешние JavaScript-функции через `#[wasm_bindgen]`, как мы делали с `alert()`, можно использовать крейт [`web-sys`](https://crates.io/crates/web-sys). Он предоставляет привязки к JavaScript Web API, доступным в браузере. Однако большинство этих API нужно включать вручную, по отдельным feature-флагам.
-Добавьте крейт `web-sys` в проект, включив все нужные фичи:
+Добавьте крейт `web-sys` в проект, включив все нужные feature-флаги:
```
cargo add web-sys --features "Window,Document,HtmlElement,HtmlImageElement,Blob,Url"
```
diff --git a/rust-training/src/rust-in-the-cloud.md b/rust-training/src/rust-in-the-cloud.md
index cea2bd2..f36d485 100644
--- a/rust-training/src/rust-in-the-cloud.md
+++ b/rust-training/src/rust-in-the-cloud.md
@@ -25,7 +25,7 @@ cargo binstall cargo-lambda
### 5.2.1.B Роутер axum с lambda_http
-Крейт [`lambda_runtime`](https://crates.io/crates/lambda_runtime/) предоставляет рантайм для AWS Lambda, написанных на Rust. Крейт [`lambda_http`](https://crates.io/crates/lambda_http) добавляет слой абстракции поверх `lambda_runtime`, который упрощает разработку HTTP-серверов на AWS Lambda с помощью Rust. Это идеально подходит для небольших динамических сайтов и REST API.
+Крейт [`lambda_runtime`](https://crates.io/crates/lambda_runtime/) предоставляет рантайм для функций AWS Lambda, написанных на Rust. Крейт [`lambda_http`](https://crates.io/crates/lambda_http) добавляет слой абстракции поверх `lambda_runtime`, который упрощает разработку HTTP-серверов на AWS Lambda с помощью Rust. Это идеально подходит для небольших динамических сайтов и REST API.
Добавьте `lambda_http` в проект командой:
```
@@ -74,7 +74,7 @@ cargo lambda build --release --arm64 --output-format zip
```
Эта команда создаст файл `bootstrap.zip` в папке `target/lambda/{имя проекта}`, который можно загрузить в консоль AWS, чтобы развернуть Lambda.
-Однако этот zip-файл не содержит наши ресурсы. Если мы хотим, чтобы Lambda отдавала HTML-документ, а также соответствующие CSS-файл и изображение, эти ресурсы нужно включить в архив. Создадим конфигурационный файл `CargoLambda.toml`, в котором опишем, как собирать Lambda, и добавим в него следующее:
+Однако этот zip-файл не содержит наших ресурсов. Если мы хотим, чтобы Lambda отдавала HTML-документ, а также соответствующие CSS-файл и изображение, эти ресурсы нужно включить в архив. Создадим конфигурационный файл `CargoLambda.toml`, в котором опишем, как собирать Lambda, и добавим в него следующее:
```toml
[build]
arm64 = true
diff --git a/rust-training/src/testing-and-fuzzing.md b/rust-training/src/testing-and-fuzzing.md
index aca3ae2..2a1f20c 100644
--- a/rust-training/src/testing-and-fuzzing.md
+++ b/rust-training/src/testing-and-fuzzing.md
@@ -22,11 +22,11 @@ cargo install cargo-llvm-cov
```
После этого посмотреть покрытие можно, запустив `cargo llvm-cov` из каталога крейта. Также можно выполнить `cargo llvm-cov --open`, чтобы открыть отчёт о покрытии в браузере.
-Хотя покрытие строк высокое, как видно, оно не равно 100%. Напишите модульный тест, чтобы покрытие строк для `src/lib.rs` *действительно* достигло 100% (на практике этого редко удаётся добиться).
+Хотя покрытие строк высокое, оно, как видно, не равно 100%. Напишите модульный тест, чтобы покрытие строк для `src/lib.rs` *действительно* достигло 100% (на практике этого редко удаётся добиться).
## Упражнение 3.2.1.B: Фаззинг
-Даже при 100% покрытии в коде могут скрываться ошибки. Найдём их с помощью `cargo-fuzz`. Чтобы его установить, нужно не только установить `cargo-fuzz`, но и использовать тулчейн «nightly», который содержит все экспериментальные возможности. Установить оба инструмента можно так:
+Даже при 100% покрытии в коде могут скрываться ошибки. Найдём их с помощью `cargo-fuzz`. Для него нужен не только сам `cargo-fuzz`, но и тулчейн «nightly», в котором доступны все экспериментальные возможности. Установить оба можно так:
```bash
rustup toolchain install nightly
diff --git a/rust-training/src/traits-and-generics.md b/rust-training/src/traits-and-generics.md
index 7015c6a..7f988c4 100644
--- a/rust-training/src/traits-and-generics.md
+++ b/rust-training/src/traits-and-generics.md
@@ -24,7 +24,7 @@
Подсказка 2 (трейты `Add` и `Mul`)
- У трейтов `Add` и `Mul` есть обобщённый associated-тип `Output`. Именно поэтому мы смогли реализовать скалярное произведение как трейт `Mul` для `Vec2D`, задав в качестве результата число. В обобщённой реализации мы хотим, чтобы тип `T` можно было складывать и/или умножать. Для этого добавляем к `T` ограничения `Add` и/или `Mul`, но также нужно указать, какой результат ожидаем от сложения или умножения двух значений `T`, например так: `T: Add<Output = T>`.
+ У трейтов `Add` и `Mul` есть ассоциированный тип `Output`. Именно поэтому мы смогли реализовать скалярное произведение как трейт `Mul` для `Vec2D`, задав в качестве результата число. В обобщённой реализации мы хотим, чтобы тип `T` можно было складывать и/или умножать. Для этого добавляем к `T` ограничения `Add` и/или `Mul`, но также нужно указать, какой результат ожидаем от сложения или умножения двух значений `T`, например так: `T: Add<Output = T>`.
Раскомментируйте тесты `float_addition` и `float_dot_product`, чтобы проверить, что `Vec2D` теперь работает и с числами с плавающей точкой!
@@ -32,15 +32,15 @@
## Упражнение 2.4.2: Вектор с локальным хранилищем (`LocalStorageVec`)
-Это бонусное упражнение! Мы создадим тип `LocalStorageVec`, обобщённый список элементов, который хранится либо на стеке, либо в куче, в зависимости от размера. Если элементы достаточно малы, чтобы поместиться на стеке, буфер `LocalStorageVec` реализован массивом. `LocalStorageVec` обобщён не только по типу (`T`) элементов списка, но и по размеру (`N`) массива на стеке, используя относительно новую возможность языка, [константные обобщения (const generics)](https://doc.rust-lang.org/reference/items/generics.html#const-generics). Как только в `LocalStorageVec` оказывается больше элементов, чем помещается в массив, выделяется [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html) в куче, где и будут храниться элементы.
+Это бонусное упражнение! Мы создадим тип `LocalStorageVec`, обобщённый список элементов, который хранится либо на стеке, либо в куче, в зависимости от размера. Если элементы достаточно малы, чтобы поместиться на стеке, буфер `LocalStorageVec` реализован массивом. `LocalStorageVec` обобщён не только по типу (`T`) элементов списка, но и по размеру (`N`) массива на стеке — для этого используется относительно новая возможность языка, [константные обобщения (const generics)](https://doc.rust-lang.org/reference/items/generics.html#const-generics). Как только в `LocalStorageVec` оказывается больше элементов, чем помещается в массив, выделяется [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html) в куче, где и будут храниться элементы.
-**В этом упражнении цели помечены звёздочками (⭐), которые показывают сложность. Скорее всего, вы не успеете выполнить все упражнения во время занятия.**
+**В этом упражнении подзадачи помечены звёздочками (⭐), которые показывают сложность. Скорее всего, вы не успеете выполнить все упражнения во время занятия.**
**Вопросы**
1. Когда такая структура данных эффективнее обычного `Vec`?
2. Каковы её недостатки по сравнению с обычным `Vec`?
-Откройте крейт `exercises/2-foundations-of-rust/4-traits-and-generics/2-local-storage-vec`. В нём есть файл `src/lib.rs`, то есть этот крейт — библиотека. В `lib.rs` есть набор тестов, которые запускаются командой `cargo test`. Не беспокойтесь, если они пока не проходят или даже не компилируются: в этом упражнении ваша задача — это исправить. Большинство тестов сейчас закомментированы, чтобы можно было идти шаг за шагом. **Прежде чем начать, посмотрите код и комментарии в нём: там много полезных подсказок.**
+Откройте крейт `exercises/2-foundations-of-rust/4-traits-and-generics/2-local-storage-vec`. В нём есть файл `src/lib.rs`, то есть этот крейт — библиотека. В `lib.rs` есть набор тестов, которые запускаются командой `cargo test`. Не беспокойтесь, если они пока не проходят или даже не компилируются: в этом упражнении ваша задача как раз в том, чтобы это исправить. Большинство тестов сейчас закомментированы, чтобы можно было идти шаг за шагом. **Прежде чем начать, посмотрите код и комментарии в нём: там много полезных подсказок.**
### 2.4.2.A Определяем тип ⭐
Сейчас перечисление `LocalStorageVec` (`enum`) не завершено. Добавьте в него два варианта: `Stack` и `Heap`. `Stack` содержит два именованных поля: `buf` и `len`. `buf` — массив, вмещающий `N` элементов типа `T`; `len` — поле типа `usize`, которое хранит количество реально сохранённых элементов. Вариант `Heap` содержит безымянное поле с `Vec`. Если варианты определены правильно, запуск `cargo test` должен вывести примерно следующее:
@@ -91,7 +91,7 @@ impl From> for LocalStorageVec {
```
**Вопрос**
-1. Как бы вы по-английски прочитали первую строку кода, которую только что скопировали?*
+1. Как бы вы по-английски произнесли вслух первую строку кода, которую только что скопировали?
Запустите `cargo test`, чтобы проверить реализацию.
@@ -116,7 +116,7 @@ impl From> for LocalStorageVec {
Далее реализуем методы `len`, `push`, `pop`, `insert`, `remove` и `clear`:
- `len` возвращает длину `LocalStorageVec`;
- `push` добавляет элемент в конец `LocalStorageVec` и увеличивает длину. Если содержимое больше не помещается на стеке, оно может быть перенесено в кучу;
-- `pop` удаляет элемент с конца `LocalStorageVec`, возвращает его (опционально) и уменьшает длину. Если длина равна 0, `pop` возвращает `None`;
+- `pop` удаляет элемент с конца `LocalStorageVec`, возвращает его (в виде `Option`) и уменьшает длину. Если длина равна 0, `pop` возвращает `None`;
- `insert` вставляет элемент по заданному индексу и увеличивает длину `LocalStorageVec`;
- `remove` удаляет элемент по заданному индексу и возвращает его;
- `clear` сбрасывает длину `LocalStorageVec` в 0.
@@ -154,11 +154,11 @@ pub struct LocalStorageVecIter {
Каждую из этих реализаций можно выразить через реализацию `as_ref`, поскольку срезы `[T]` поддерживают индексирование всеми перечисленными типами. То есть `[T]` тоже реализует `Index` для этих типов. Раскомментируйте тестовый случай `it_indexes` и запустите `cargo test`, чтобы проверить реализацию.
### 2.4.2.G Снимаем ограничения ⭐⭐
-Когда мы реализовывали итератор, заимствующий данные, мы видели, что методы можно определять в разных блоках `impl` с разными ограничениями на типы. Часть написанного нами функционала опиралась на допущение, что `T` одновременно реализует `Copy` и `Default`. Но из-за этого каждый такой метод определён только для `LocalStorageVec`, содержащих элементы типа `T`, которые действительно реализуют `Copy` и `Default`, а это неидеально. Сколько методов можно переписать, убрав одно или оба из этих ограничений?
+Когда мы реализовывали итератор, заимствующий данные, мы видели, что методы можно определять в разных блоках `impl` с разными ограничениями на типы. Часть написанного нами кода опиралась на допущение, что `T` одновременно реализует `Copy` и `Default`. Но из-за этого каждый такой метод определён только для `LocalStorageVec`, содержащих элементы типа `T`, которые действительно реализуют `Copy` и `Default`, а это неидеально. Сколько методов можно переписать, убрав одно или оба из этих ограничений?
### 2.4.2.H Заимствующий `Iterator` ⭐⭐⭐
-У `LocalStorageVec` уже есть итератор, но у него есть ограничение: чтобы его создать, `LocalStorageVec` нужно поглотить (consume). А что, если мы хотим только перебирать элементы, не забирая их? Понадобится другой тип итератора, который содержит неизменяемую ссылку на `LocalStorageVec` и, значит, потребует аннотацию времени жизни. Добавьте в `LocalStorageVec` метод `iter`, который принимает разделяемую ссылку `&self` и создаёт заимствующий итератор. Реализуйте трейт `Iterator` с подходящим типом ссылки `Item` для вашего заимствующего итератора. Чтобы проверить код, раскомментируйте и запустите тестовый случай `it_borrowing_iters`.
+У `LocalStorageVec` уже есть итератор, но у него есть ограничение: чтобы его создать, `LocalStorageVec` нужно потребить (consume), то есть передать во владение. А что, если мы хотим только перебирать элементы, не забирая их? Понадобится другой тип итератора, который содержит неизменяемую ссылку на `LocalStorageVec` и, значит, потребует аннотацию времени жизни. Добавьте в `LocalStorageVec` метод `iter`, который принимает разделяемую ссылку `&self` и создаёт заимствующий итератор. Реализуйте трейт `Iterator` с подходящим типом ссылки `Item` для вашего заимствующего итератора. Чтобы проверить код, раскомментируйте и запустите тестовый случай `it_borrowing_iters`.
Обратите внимание: на этот раз тест не скомпилируется, если потребовать, чтобы элементы `LocalStorageVec` были `Copy`! Значит, метод `LocalStorageVec::iter` нужно определить в новом блоке `impl`, который не накладывает это ограничение на `T`:
@@ -195,7 +195,7 @@ trait LocalStorageVecIndex {}
### 2.4.2.J `Deref` и `DerefMut` ⭐⭐⭐⭐
Следующие трейты, которые сделают `LocalStorageVec` гибче, — это [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) и [`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html). Они используют возможность Rust «deref coercion», которая позволяет обращаться с типом так, будто это тот тип, на который он похож.
Благодаря этому мы сможем вызывать на `LocalStorageVec` [любой метод, определённый для `[T]`](https://doc.rust-lang.org/std/primitive.slice.html).
-Прежде чем продолжить, прочитайте раздел [«Treating a Type Like a Reference by Implementing the Deref Trait»](https://doc.rust-lang.org/book/ch15-02-deref.html#treating-a-type-like-a-reference-by-implementing-the-deref-trait) из *The Rust Programming Language* (TRPL) — раздел о том, как относиться к типу как к ссылке, реализуя трейт `Deref`.
+Прежде чем продолжить, прочитайте раздел [«Treating a Type Like a Reference by Implementing the Deref Trait»](https://doc.rust-lang.org/book/ch15-02-deref.html#treating-a-type-like-a-reference-by-implementing-the-deref-trait) из *The Rust Programming Language* (TRPL): в нём рассказано, как обращаться с типом как со ссылкой, реализовав трейт `Deref`.
**Не путайте deref coercion с наследованием! Использовать `Deref` и `DerefMut` для имитации наследования в Rust не принято.**
Ниже приведена реализация `Deref` и `DerefMut` через реализации `AsRef` и `AsMut`. Обратите внимание на то, как именно вызываются `as_ref` и `as_mut`.
diff --git a/std-training/book/src/01_intro.md b/std-training/book/src/01_intro.md
index deb9c85..8f1812a 100644
--- a/std-training/book/src/01_intro.md
+++ b/std-training/book/src/01_intro.md
@@ -6,7 +6,7 @@
Это учебный материал Ferrous Systems «Embedded Rust на Espressif». Он разделён на два практикума: вводный и продвинутый. Вводный знакомит с основами разработки встраиваемых систем и с тем, как заставить плату взаимодействовать с внешним миром: реагировать на команды и отправлять данные с датчиков.
-Продвинутый курс развивает эти темы: обработка прерываний, низкоуровневый доступ к периферии и написание собственных драйверов.
+Продвинутый практикум развивает эти темы: обработка прерываний, низкоуровневый доступ к периферии и написание собственных драйверов.
Вы можете присоединиться к [сообществу esp-rs](https://matrix.to/#/#esp-rs:matrix.org) в Matrix и задавать там любые технические вопросы. Сообщество открыто для всех.
@@ -15,7 +15,7 @@
> Espressif официально поддерживает подход `no_std` через [`esp-hal`][esp-hal]. Эквивалентный материал для официально поддерживаемого подхода см. в [курсе по `no_std`][no-std-training].
[esp-hal]: https://github.com/esp-rs/esp-hal
-[no-std-training]: https://docs.espressif.com/projects/rust/no_std-training/
+[no-std-training]: https://r007.github.io/EmbeddedRust-Rus/no-std-training/
## Переводы
diff --git a/std-training/book/src/02_1_hardware.md b/std-training/book/src/02_1_hardware.md
index c0f3c7a..d9a07f0 100644
--- a/std-training/book/src/02_1_hardware.md
+++ b/std-training/book/src/02_1_hardware.md
@@ -14,7 +14,7 @@ $ lsusb | grep USB
Bus 006 Device 035: ID 303a:1001 Espressif USB JTAG/serial debug unit
```
-Другой способ увидеть, какой порт и какие права назначены устройству, — проверить папку `/by-id`:
+Другой способ увидеть, какой порт и какие права назначены устройству, — проверить каталог `/dev/serial/by-id`:
``` console
$ ls -l /dev/serial/by-id
lrwxrwxrwx 1 root root .... usb-Espressif_USB_JTAG_serial_debug_unit_60:55:F9:C0:27:18-if00 -> ../../ttyACM0
diff --git a/std-training/book/src/02_2_software.md b/std-training/book/src/02_2_software.md
index 8b3bb55..e23dc73 100644
--- a/std-training/book/src/02_2_software.md
+++ b/std-training/book/src/02_2_software.md
@@ -4,11 +4,11 @@
🔎 Если вам нужна нестандартная установка (например, сборка компонентов из исходников или добавление поддержки целевых платформ `Xtensa`), инструкции есть в главе [Rust on ESP targets](https://esp-rs.github.io/book/installation/index.html) книги *Rust on ESP*.
-## Набор инструментов Rust
+## Тулчейн Rust
✅ Если Rust ещё не установлен на вашем компьютере, получите его на .
-Кроме того, для ESP32-C3 сейчас нужна [*nightly*-версия](https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust) набора инструментов Rust. Для этого курса мы будем использовать версию `nightly-2024-06-30`.
+Кроме того, для ESP32-C3 сейчас нужна [*nightly*-версия](https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust) тулчейна Rust. Для этого курса мы будем использовать версию `nightly-2024-06-30`.
✅ Установите *nightly*-версию Rust и добавьте поддержку целевой архитектуры командой:
@@ -24,7 +24,7 @@ rustup toolchain install nightly-2024-06-30 --component rust-src
Понадобится несколько инструментов:
- [`cargo-espflash`](https://github.com/esp-rs/espflash/tree/main/cargo-espflash) — загрузка прошивки в микроконтроллер и открытие serial-монитора с интеграцией в Cargo;
- [`espflash`](https://github.com/esp-rs/espflash/tree/main/espflash) — загрузка прошивки в микроконтроллер и открытие serial-монитора;
-- [`ldproxy`](https://github.com/esp-rs/embuild/tree/master/ldproxy) — зависимость инструментария сборки Espressif.
+- [`ldproxy`](https://github.com/esp-rs/embuild/tree/master/ldproxy) — зависимость тулчейна сборки Espressif.
✅ Установите их командой:
@@ -34,7 +34,7 @@ cargo install cargo-espflash espflash ldproxy
⚠️ Команды `espflash` и `cargo-espflash`, приведённые в книге, предполагают версию 2 или новее.
-## Зависимости инструментария
+## Зависимости тулчейна
### Debian/Ubuntu
@@ -70,7 +70,7 @@ brew install llvm libuv
## Docker
-Альтернативный вариант — использовать Docker. В репозитории есть `Dockerfile` с инструкциями по установке набора инструментов Rust и всех необходимых пакетов. **Эта виртуализированная среда предназначена для сборки бинарных файлов под целевую платформу Espressif. Прошивать бинарные файлы из контейнеров нельзя**, поэтому есть два варианта:
+Альтернативный вариант — использовать Docker. В репозитории есть `Dockerfile` с инструкциями по установке тулчейна Rust и всех необходимых пакетов. **Эта виртуализированная среда предназначена для сборки бинарных файлов под целевую платформу Espressif. Прошивать бинарные файлы из контейнеров нельзя**, поэтому есть два варианта:
- Выполнять команды прошивки, например `cargo-espflash`, в основной системе. В этом случае рекомендуется держать открытыми два терминала:
- в контейнере: собрать проект;
- в основной системе: использовать подкоманду `cargo-espflash`, чтобы прошить программу в устройство.
diff --git a/std-training/book/src/02_3_repository.md b/std-training/book/src/02_3_repository.md
index afd2689..6a5a353 100644
--- a/std-training/book/src/02_3_repository.md
+++ b/std-training/book/src/02_3_repository.md
@@ -1,12 +1,12 @@
# Репозиторий практикума
-Весь материал находится по адресу .
+Весь материал находится в каталоге [`std-training`](https://github.com/r007/EmbeddedRust-Rus/tree/main/std-training) этого репозитория.
-✅ Клонируйте репозиторий практикума и перейдите в его папку:
+✅ Клонируйте репозиторий и перейдите в папку практикума:
```console
-git clone "https://github.com/r007/EmbeddedRust-Rus/tree/main/std-training"
-cd std-training
+git clone https://github.com/r007/EmbeddedRust-Rus.git
+cd EmbeddedRust-Rus/std-training
```
❗ Пользователи Windows могут столкнуться с проблемами из-за [длинных путей][windows-long-path].
diff --git a/std-training/book/src/02_4_hello_board.md b/std-training/book/src/02_4_hello_board.md
index 6f1aca3..cb92606 100644
--- a/std-training/book/src/02_4_hello_board.md
+++ b/std-training/book/src/02_4_hello_board.md
@@ -86,7 +86,7 @@ error[E0463]: can't find crate for `core`
```
Вы пытаетесь собрать проект на `stable` Rust, а нужен `nightly`.
-Это сообщение об ошибке немного вводит в заблуждение: этот таргет *нельзя* установить. Его нужно собрать из исходников с помощью `build-std`, а эта функция доступна только в nightly.
+Это сообщение об ошибке немного вводит в заблуждение: эту целевую платформу *нельзя* установить. Его нужно собрать из исходников с помощью `build-std`, а эта функция доступна только в nightly.
---
@@ -102,7 +102,7 @@ error: cannot find macro `llvm_asm` in this scope
CMake Error at .../Modules/CMakeDetermineSystem.cmake:129 (message):
```
-Установка инструментария Espressif могла повредиться. Удалите её и запустите сборку заново, чтобы инициировать новую загрузку:
+Установка тулчейна Espressif могла повредиться. Удалите её и запустите сборку заново, чтобы инициировать новую загрузку:
```console
rm -rf ~/.espressif
diff --git a/std-training/book/src/03_0_intro_workshop.md b/std-training/book/src/03_0_intro_workshop.md
index 0449882..ae77712 100644
--- a/std-training/book/src/03_0_intro_workshop.md
+++ b/std-training/book/src/03_0_intro_workshop.md
@@ -1,6 +1,6 @@
# Вводный практикум
-Этот практикум познакомит вас с основами разработки встраиваемых систем. К концу практикума мы научимся взаимодействовать с внешним миром: отправлять и получать команды от датчиков платы и к ним. Программа включает:
+Этот практикум познакомит вас с основами разработки встраиваемых систем. К концу практикума мы научимся взаимодействовать с внешним миром, в том числе отправлять команды плате и получать данные с её датчиков. Программа включает:
- Обзор структуры проекта.
- Создание проекта с помощью `cargo-generate`.
- Написание HTTP-клиента.
diff --git a/std-training/book/src/03_1_project_orga.md b/std-training/book/src/03_1_project_orga.md
index 2dd49e6..864c096 100644
--- a/std-training/book/src/03_1_project_orga.md
+++ b/std-training/book/src/03_1_project_orga.md
@@ -15,9 +15,9 @@
Подробнее — в главе [об экосистеме](https://esp-rs.github.io/book/overview/using-the-standard-library.html) книги The Rust on ESP Book.
-### Инструментарий сборки
+### Тулчейн сборки
-🔎 В процессе сборки проекта `esp-idf-sys` загружает [ESP-IDF](https://github.com/espressif/esp-idf) — основанный на C инструментарий Espressif. Каталог загрузки можно настроить. Чтобы сэкономить место на диске и время загрузки, все примеры и упражнения в репозитории практикума используют один общий (`global`) инструментарий, установленный в `~/.espressif` (в Windows — `%USERPROFILE%\.espressif`). Другие варианты см. в описании параметра `ESP_IDF_TOOLS_INSTALL_DIR` в [README](https://github.com/esp-rs/esp-idf-sys#configuration) `esp-idf-sys`.
+🔎 В процессе сборки проекта `esp-idf-sys` загружает [ESP-IDF](https://github.com/espressif/esp-idf) — основанный на C набор инструментов Espressif. Каталог загрузки можно настроить. Чтобы сэкономить место на диске и время загрузки, все примеры и упражнения в репозитории практикума используют один общий (`global`) экземпляр этого набора, установленный в `~/.espressif` (в Windows — `%USERPROFILE%\.espressif`). Другие варианты см. в описании параметра `ESP_IDF_TOOLS_INSTALL_DIR` в [README](https://github.com/esp-rs/esp-idf-sys#configuration) `esp-idf-sys`.
## Структура пакета
diff --git a/std-training/book/src/03_2_cargo_generate.md b/std-training/book/src/03_2_cargo_generate.md
index 40d607b..4d52923 100644
--- a/std-training/book/src/03_2_cargo_generate.md
+++ b/std-training/book/src/03_2_cargo_generate.md
@@ -39,7 +39,7 @@ cargo generate esp-rs/esp-idf-template cargo
🔎 `.cargo/config.toml` содержит локальные настройки ([список всех настроек](https://doc.rust-lang.org/cargo/reference/config.html)) для вашего пакета.
`Cargo.toml` содержит зависимости, а `Cargo.lock` [фиксирует все ваши зависимости](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html).
-Необязательно, но рекомендуется: чтобы сэкономить место на диске и время загрузки, задайте [общий каталог инструментария](https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md#esp_idf_tools_install_dir-esp_idf_tools_install_dir). Иначе каждый новый проект или рабочее пространство получит собственную копию инструментария на вашем компьютере:
+Необязательно, но рекомендуется: чтобы сэкономить место на диске и время загрузки, задайте [общий каталог инструментов](https://github.com/esp-rs/esp-idf-sys/blob/master/BUILD-OPTIONS.md#esp_idf_tools_install_dir-esp_idf_tools_install_dir). Иначе каждый новый проект или рабочее пространство получит собственную копию этих инструментов на вашем компьютере:
✅ Откройте `hello-world/.cargo/config.toml` и добавьте следующую строку в конец секции `[env]`. Остальное не меняйте.
diff --git a/std-training/book/src/03_3_2_http_client.md b/std-training/book/src/03_3_2_http_client.md
index b958204..05b839b 100644
--- a/std-training/book/src/03_3_2_http_client.md
+++ b/std-training/book/src/03_3_2_http_client.md
@@ -31,7 +31,7 @@ cargo run --example http_client
✅ Получите клиент из только что созданного соединения.
-Вызов HTTP-функций (например, `get(url)`) у этого клиента возвращает `embedded_svc::http::client::Request`, который нужно отправить, чтобы учесть возможность клиента передать данные вместе с запросом.
+Вызов HTTP-методов клиента (например, `get(url)`) возвращает `embedded_svc::http::client::Request`. Его нужно отправить явно: клиент может передавать данные вместе с запросом.
Функция `get` использует [as_ref()](https://doc.rust-lang.org/std/convert/trait.AsRef.html). Это значит, что вместо ограничения одним конкретным типом, например только `String` или только `&str`, функция принимает любой тип, реализующий трейт `AsRef`, то есть любой тип, для которого вызов `.as_ref()` даёт `&str`. Это работает для `String` и `&str`, а также для перечисления `Cow`, которое содержит один из двух предыдущих вариантов.
@@ -56,7 +56,7 @@ match status {
Ошибку статуса можно вернуть с помощью крейта [Anyhow](https://docs.rs/anyhow/latest/anyhow/index.html). Он содержит различные средства для упрощения обработки ошибок на уровне приложения. Крейт предоставляет универсальный `anyhow::Result`, который оборачивает успешный случай (`Ok`) в T и избавляет от необходимости указывать тип Err, при условии что каждая возвращаемая ошибка реализует `std::error::Error`.
-✅ Читайте полученные данные по частям в буфер `u8` с помощью `Read::read(&mut reader,&mut buf)`. `Read::read` возвращает количество прочитанных байт. Чтение завершено, когда это значение равно `0`.
+✅ Читайте полученные данные по частям в буфер байтов (`u8`) с помощью `Read::read(&mut reader,&mut buf)`. `Read::read` возвращает количество прочитанных байт. Чтение завершено, когда это значение равно `0`.
✅ Выведите общее количество прочитанных байт.
diff --git a/std-training/book/src/03_4_http_server.md b/std-training/book/src/03_4_http_server.md
index 35298bb..9a715b3 100644
--- a/std-training/book/src/03_4_http_server.md
+++ b/std-training/book/src/03_4_http_server.md
@@ -63,7 +63,7 @@ server.fn_handler(path, Method::Get, |request| {
✅ Напишите второй обработчик, который отдаёт температуру чипа по адресу `http:///temperature`, используя готовую функцию `temperature(val: f32)` для генерации HTML-строки.
💡 Чтобы отправить строку ответа, её нужно преобразовать в срез `&[u8]` через `a_string.as_bytes()`.
-💡 Датчику температуры нужен эксклюзивный (изменяемый) доступ. Передать его в обработчик по значению не получится: он будет уничтожен после первого вызова. Это можно исправить, сделав обработчик замыканием `move ||`, обернув датчик в `Arc>`, оставив один `clone()` этого `Arc` в функции `main`, а другой переместив в замыкание.
+💡 Датчику температуры нужен эксклюзивный (изменяемый) доступ. Передать его в обработчик по значению не получится: он будет уничтожен после первого вызова. Это решается так: сделайте обработчик замыканием `move ||` и оберните датчик в `Arc>`; один `clone()` этого `Arc` останется в функции `main`, а другой переместите в замыкание.
## Устранение неполадок
diff --git a/std-training/book/src/03_5_1_mqtt.md b/std-training/book/src/03_5_1_mqtt.md
index 147bd77..568cd15 100644
--- a/std-training/book/src/03_5_1_mqtt.md
+++ b/std-training/book/src/03_5_1_mqtt.md
@@ -4,7 +4,7 @@
-Чтобы завершить вводный курс, добавим на плату немного функциональности [IoT](https://en.wikipedia.org/wiki/Internet_of_things). Наша цель — заставить плату отправлять обновления показаний датчиков в реальном времени, без постоянного опроса, как пришлось бы делать с HTTP-сервером, а также получать команды для изменения цвета светодиода платы.
+Чтобы завершить вводный практикум, добавим на плату немного функциональности [IoT](https://en.wikipedia.org/wiki/Internet_of_things). Наша цель — заставить плату отправлять обновления показаний датчиков в реальном времени, без постоянного опроса, как пришлось бы делать с HTTP-сервером, а также получать команды для изменения цвета светодиода платы.
Это можно смоделировать с помощью [архитектуры «издатель–подписчик»](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern): несколько клиентов публикуют сообщения в определённых каналах (топиках) и могут подписываться на эти топики, чтобы получать сообщения от других. Доставкой сообщений управляет брокер — в нашем случае это сервер MQTT.
diff --git a/std-training/book/src/03_5_2_mqtt.md b/std-training/book/src/03_5_2_mqtt.md
index 377738c..26915d9 100644
--- a/std-training/book/src/03_5_2_mqtt.md
+++ b/std-training/book/src/03_5_2_mqtt.md
@@ -11,7 +11,7 @@
Клиент также генерирует случайные RGB-цвета и публикует их в топике.
**Это важно только для второй части упражнения**.
-⚠️ Как и в упражнениях с HTTP, нужно настроить данные для подключения в `cfg.toml` для **обеих программ**. Помимо данных Wi-Fi, нужно добавить параметры сервера MQTT. Нужные настройки смотрите в каждом `cfg.toml.example`. Напомним: имя в квадратных скобках в `cfg.toml` — это имя пакета из `Cargo.toml`.
+⚠️ Как и в упражнениях с HTTP, нужно задать данные для подключения в `cfg.toml` **обеих программ**. Помимо данных Wi-Fi, нужно добавить параметры сервера MQTT. Нужные настройки смотрите в каждом `cfg.toml.example`. Напомним: имя в квадратных скобках в `cfg.toml` — это имя пакета из `Cargo.toml`.
Структура упражнения показана ниже. В этой части мы сосредоточимся на топике температуры.
@@ -70,7 +70,7 @@ let mut client = EspMqttClient::new(broker_url,
Крейт `mqtt_messages` (находится в `common/lib`) помогает работать с сообщениями, подписками и топиками:
### Функции для формирования строк топиков
-- `color_topic(uuid)` — создаёт топик для отправки цветов, которые будут опубликованы на плату.
+- `color_topic(uuid)` — создаёт топик, в который публикуются цвета для платы.
- `hello_topic(uuid)` — тестовый топик для первоначальной проверки успешного подключения;
- `temperature_data_topic(uuid)` — создаёт полную строку топика «temperature».
diff --git a/std-training/book/src/03_5_3_mqtt.md b/std-training/book/src/03_5_3_mqtt.md
index 82e8973..46b422b 100644
--- a/std-training/book/src/03_5_3_mqtt.md
+++ b/std-training/book/src/03_5_3_mqtt.md
@@ -46,7 +46,7 @@ client.subscribe(subscribe_topic, QoS::AtLeastOnce)
{{#include ../../intro/mqtt/exercise/examples/solution_publ_rcv.rs:mqtt_client}}
```
-В функции обработки вы будете обрабатывать сообщения `Complete`.
+В обработчике нужно обрабатывать сообщения `Complete`.
💡 Используйте Rust Analyzer, чтобы сгенерировать недостающие ветки `match`, или обработайте любой другой тип ответа, выведя его через `info!()`.
diff --git a/std-training/book/src/04_0_advanced_workshop.md b/std-training/book/src/04_0_advanced_workshop.md
index aa0f713..968a9be 100644
--- a/std-training/book/src/04_0_advanced_workshop.md
+++ b/std-training/book/src/04_0_advanced_workshop.md
@@ -1,6 +1,6 @@
# Продвинутый практикум
-В этом курсе мы углубимся в темы, которые относятся только к встраиваемым системам и/или близки к железу, в первую очередь к низкоуровневому вводу-выводу. В отличие от первой части, мы не будем использовать только высокоуровневые абстракции, которые, например, скрывают настройку выводов. Вместо этого вы научитесь настраивать их сами. Также вы научитесь писать напрямую в регистры и выяснять, какой регистр для этого нужен. Вопросы владения и безопасности памяти мы разберём в контексте упражнений.
+В этом практикуме мы углубимся в темы, которые относятся только к встраиваемым системам и/или близки к железу, в первую очередь к низкоуровневому вводу-выводу. В отличие от первой части, мы не будем ограничиваться высокоуровневыми абстракциями, которые, например, скрывают настройку выводов. Вместо этого вы научитесь настраивать их сами. Также вы научитесь писать напрямую в регистры и выяснять, какой регистр для этого нужен. Вопросы владения и безопасности памяти мы разберём в контексте упражнений.
Эта часть состоит из трёх упражнений.
diff --git a/std-training/book/src/04_3_2_i2c.md b/std-training/book/src/04_3_2_i2c.md
index 676691c..91dc54d 100644
--- a/std-training/book/src/04_3_2_i2c.md
+++ b/std-training/book/src/04_3_2_i2c.md
@@ -16,7 +16,7 @@
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:struct}}
```
-Добавляем блок `impl`, который будет содержать все методы, доступные для экземпляра датчика. В нём также определяется обработка ошибок. В этом же блоке реализуем метод создания экземпляра. Методы могут быть публичными или приватными. Этот метод должен быть доступен извне, поэтому он помечен как `pub`. Обратите внимание: записанный таким образом, экземпляр датчика становится владельцем шины I²C.
+Добавляем блок `impl`, который будет содержать все методы, доступные для экземпляра датчика. В нём также определяется обработка ошибок. В этом же блоке реализуем метод создания экземпляра. Методы могут быть публичными или приватными. Этот метод должен быть доступен извне, поэтому он помечен как `pub`. Обратите внимание: при такой записи экземпляр датчика становится владельцем шины I²C.
```rust
{{#include ../../advanced/i2c-driver/src/icm42670p_solution.rs:impl}}
@@ -31,7 +31,7 @@
```
- У этого устройства I²C два возможных адреса: `0x68` и `0x69`.
-Мы указываем устройству, какой адрес использовать, подавая на вывод `AP_AD0` либо `0V`, либо `3.3V`. При `0V` устройство отвечает на адрес `0x68`, при `3.3V` — на `0x69`. Поэтому вывод `AD_AD0` можно считать однобитным входом, который задаёт младший бит адреса устройства.
+Мы указываем устройству, какой адрес использовать, подавая на вывод `AP_AD0` либо `0V`, либо `3.3V`. При `0V` устройство отвечает на адрес `0x68`, при `3.3V` — на `0x69`. Поэтому вывод `AP_AD0` можно считать однобитным входом, который задаёт младший бит адреса устройства.
Подробнее — в [даташите, раздел 9.3](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf).
### Представление регистров
diff --git a/std-training/book/src/04_3_3_i2c.md b/std-training/book/src/04_3_3_i2c.md
index 5dc5193..b97223d 100644
--- a/std-training/book/src/04_3_3_i2c.md
+++ b/std-training/book/src/04_3_3_i2c.md
@@ -20,7 +20,7 @@
✅ У этого устройства I²C два возможных адреса. Найдите их в [даташите, раздел 9.3](https://invensense.tdk.com/wp-content/uploads/2021/07/DS-000451-ICM-42670-P-v1.0.pdf).
-🔎 Мы указываем устройству, какой адрес использовать, подавая на вывод `AP_AD0` либо `0V`, либо `3.3V`. При `0V` устройство отвечает на адрес `0x68`, при `3.3V` — на `0x69`. Поэтому вывод `AD_AD0` можно считать однобитным входом, который задаёт младший бит адреса устройства.
+🔎 Мы указываем устройству, какой адрес использовать, подавая на вывод `AP_AD0` либо `0V`, либо `3.3V`. При `0V` устройство отвечает на адрес `0x68`, при `3.3V` — на `0x69`. Поэтому вывод `AP_AD0` можно считать однобитным входом, который задаёт младший бит адреса устройства.
✅ Создайте перечисление, которое представляет оба варианта адреса. Значения вариантов должны быть записаны в двоичном виде.
diff --git a/std-training/book/src/04_4_2_interrupts.md b/std-training/book/src/04_4_2_interrupts.md
index e402fc7..91ac1fb 100644
--- a/std-training/book/src/04_4_2_interrupts.md
+++ b/std-training/book/src/04_4_2_interrupts.md
@@ -13,7 +13,7 @@ cargo run --example solution_led
## 💡 Подсказки
* Нужные импорты уже есть. Если выполнить `cargo doc --open`, вы получите полезную документацию по светодиоду.
-* Артикул светодиода — WS2812RMT.
+* Тип светодиода — WS2812RMT.
* Это программируемый RGB-светодиод. Это значит, что нет отдельных выводов для красного, зелёного и синего, а нужно создать его экземпляр, чтобы отправлять ему значения типа `RGB8` через метод.
* На плате есть аппаратный генератор случайных чисел. Его можно вызвать через `esp_random()`.
* Вызов функций из `esp-idf-svc::sys` с точки зрения Rust небезопасен и требует блока `unsafe()`. Можно считать, что эти функции безопасны в использовании, поэтому других мер не требуется.
diff --git a/std-training/book/src/04_4_3_interrupts.md b/std-training/book/src/04_4_3_interrupts.md
index d2b12f0..5993c58 100644
--- a/std-training/book/src/04_4_3_interrupts.md
+++ b/std-training/book/src/04_4_3_interrupts.md
@@ -29,7 +29,7 @@
_ => {},
```
-4. **Необязательно**: если вы собираетесь переиспользовать этот код в другом месте, имеет смысл вынести его в отдельную функцию. Так мы подробно разберём, какие части кода должны находиться в блоках `unsafe`.
+4. **Необязательно**: если вы собираетесь переиспользовать этот код в другом месте, имеет смысл вынести его в отдельную функцию. Заодно можно чётко определить, какие части кода должны находиться в блоках `unsafe`.
```rust
// ...
diff --git a/std-training/book/src/05_reference.md b/std-training/book/src/05_reference.md
index 5b4f6af..c11de9d 100644
--- a/std-training/book/src/05_reference.md
+++ b/std-training/book/src/05_reference.md
@@ -12,7 +12,7 @@ GPIO можно настроить одним из нескольких спос
Floating (плавающий): плавающий вывод не подключён ни к VCC, ни к земле. Он просто принимает то напряжение, которое на него подано. Однако учтите: схема должна подтягивать вывод внешним образом к низкому или высокому уровню, потому что КМОП-устройства (например, микроконтроллеры) могут работать некорректно, если вывод дольше нескольких микросекунд находится выше «порога низкого уровня» `Vtl`, но ниже «порога высокого уровня» `Vth`.
-Push-Pull-Output (двухтактный выход): вывод, настроенный как двухтактный выход, может либо выставлять на себя высокое напряжение (то есть подключаться к VCC), либо низкое (подключаться к земле). Это удобно для светодиодов, зуммеров и других устройств, которые потребляют немного энергии.
+Push-Pull-Output (двухтактный выход): вывод, настроенный как двухтактный выход, может либо выставлять на себя высокое напряжение (то есть подключаться к VCC), либо низкое (подключаться к земле). Это удобно для светодиодов, пищалок и других устройств, которые потребляют немного энергии.
Open-Drain-Output (выход с открытым стоком): выходы с открытым стоком переключаются между состояниями «отключено» и «подключено к земле». Предполагается, что внешний резистор слабо подтягивает линию к VCC. Такой выход позволяет соединять несколько устройств вместе: линия находится в «низком» состоянии, если хотя бы одно из подключённых устройств притягивает её к земле. Если два или больше устройств притягивают её к земле одновременно, ничего не повреждается (соединение земли с землёй безопасно). Если ни одно из них не притягивает линию вниз, резистор по умолчанию подтянет её к высокому уровню.