У меня есть для вас интересная возможность в области встроенных систем. Компания-лидер на рынке ищет инженера по программному обеспечению, и, просматривая ваш профиль, я думаю, что вы отлично подходите на эту должность. Мы предлагаем отличную зарплату, невероятные преимущества и много печенья.
Присоединяйтесь к нам, присоединяйтесь к нам, присоединяйтесь к нам.

Выше приведен пример типичного сообщения — хорошо, последняя часть может отличаться — от рекрутера через Linkedin, когда они ищут нового инженера по прошивке.

Теперь давайте рассмотрим идею о том, что мы имеем в виду не рекрутера из последнего и величайшего блокчейн-стартапа, а говорим о серьезных компаниях, которые могут быть привлекательными, таких как Apple. , Квалком, Интел.

В этом случае ваш разум может загореться и заставить вас поделиться своим резюме с рекрутером.

Коммуникация

Следующим шагом будет согласование дня для разговора, сначала с рекрутером, либо с самим менеджером по найму.

СОВЕТ №1: не указывайте ОДИН день и ОДИН раз.
Обеспечьте не менее не менее 3 дней дополнительных часов доступности в течение той же недели. Если вы не можете предоставить 3 дня в течение одной недели, извините и предложите третий день через неделю. У крупных техников множество приложений, и даже если вы молодая и добрая версия Линуса Торвальдса, они могут выжить и без вашего вклада.
Не ведите себя как суперзвезда.

Кроме того, во время общения, будь то личное общение с Тимом Куком или последним нанятым сотрудником отдела кадров, всегда будьте добры и вежливы. Откройте электронное письмо с помощью « Привет» и закройте его как минимум с « Спасибо и с наилучшими пожеланиями ».

Интервью (и суть этой статьи)

Наконец-то мы смогли достичь того момента, когда кто-то будет задавать вам вопросы, а вы должны все знать.

СОВЕТ № 2. Это неправда.
Вы не должны знать все. Идея интервью, первых шагов, должна заключаться в том, чтобы понять, подходите ли вы для этой должности не только с точки зрения технических навыков, но и социальных навыков и решения проблем.

Поэтому не нужно знать все. На самом деле, вам не нужно знать все, что перечислено в этом сумасшедшем описании предложения о работе.

СОВЕТ №3. Всегда откликайтесь на вакансию, даже если вы не соответствуете всем требованиям. Никто никогда не соответствует им всем, и никто с другой стороны никогда не ожидает, что это будет. Для инженеров в компьютерной сфере существует масса вакансий, но инженеров не хватает, чтобы удовлетворить спрос.
Даже такие компании, как Apple и Google, которые ежедневно получают тонны резюме, испытывают трудности с поиском нужных талантов для найма.

После этого начала давайте перейдем к техническим темам, касающимся собеседований для инженеров по прошивке.

Меньше алгоритмов, больше манипуляций с битами

Довольно часто путают разработку прошивки с разработкой программного обеспечения. Мы оба пишем код, и поэтому проблемы, с которыми мы сталкиваемся, одинаковы, верно?
Нет, неправильно.

У многих людей есть эта привычка по умолчанию готовить интервью, сосредотачиваясь на этих удивительно бессмысленных задачах кода, с помощью таких замечательных инструментов, как HackerRank и Leetcode.

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

Если вы хотите взглянуть на 10 наиболее часто задаваемых алгоритмических проблем во время собеседования по кодированию, вас обслужили, но если вы хотите произвести впечатление во время скрининга позиции инженера прошивки, изучите свои приемы манипулирования битами.

Если вы ничего не знаете о Bit Manipulation, не паникуйте. Есть несколько простых правил, которые вы можете запомнить и использовать во время собеседования, чтобы найти собственное решение каждой проблемы.

Несколько принципов работы с битами

Одна вещь, которую вы должны повторять, — это основные арифметические операции между двоичными числами:

  • Добавление 0110 + 0010 = 1000
  • Вычитание 0110–0011 = 0011
  • Умножение 0011 * 0101 = 1111

Двигаясь вперед, есть все таблицы побитовых операций, которые вы не можете пропустить — ИЛИ, НЕ, И, XOR — и несколько советов и приемов, таких как следующие, относительно операции XOR (^ с этого момента).

Наконец, если вас попросят выполнить простые операции с этими операторами или даже поменять местами два числа, Xor Swap всегда будет чем-то, что может понравиться кому-то с другой стороны.

Easy Peasy УЗНАТЬ ЭТО

У нас есть идея, у нас есть принципы, и у нас есть трюк, чтобы произвести впечатление на интервьюера.

Настало время взглянуть на самые полезные быстрые упражнения, которые вас могут попросить сделать. Ничего сложного, но все же стоит иметь в виду, будьте готовы к тому времени, когда вас попросят. Они будут написаны на C, но если вы читаете этот текст, я тоже не должен этого замечать.

Наконец, небольшое и полное упражнение.

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

Ваш интервьюер заслуживает C

Мы можем считать битовую манипуляцию уже заархивированной. Пришло время перейти к чему-то более веселому и менее интеллектуальному.

Язык C является бесспорным королем разработки встроенного ПО вместе со своим братом C++.
Сейчас кому-то хотелось бы выкинуть этих парней из игры, но я не могу поверить, что через 10 лет мы будем использовать Rust или Carbon от Google вместо любимого создания Денниса Ритчи.

С учетом сказанного давайте прокрутим и посмотрим на самый распространенный вопрос (с ответами, не беспокойтесь) для инженера по программному обеспечению относительно программирования на C.

Что такое структура

В наши дни это почти клише. Я не могу вспомнить интервью за последние 5 лет, где бы интервьюер не спросил меня, что такое структура. Я рассматриваю идею о том, что это суеверный ритуал, как забавный способ попросить опрашиваемого: «Пожалуйста, будьте хотя бы приличны в своих знаниях».

Однако что такое структура в C? struct – это ключевое слово C, определяющее новый тип данных, который содержит другие типы данных вместе в уникальной структуре.

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

Что мы можем добавить? В разработке микропрограммного обеспечения важно управление памятью, поэтому, возможно, стоит упомянуть, что структура занимает объем памяти, равный или превышающий сумму занимаемой памяти все его внутренние типы.

Что это значит? Означает, что если структура содержит четыре символа, она будет занимать четыре байта в памяти. Это интуитивно просто а? Что происходит, когда структура содержит 2 символа и 1 целое число в 32-битной системе?

У нас занято 6 байт и осталось 2, так как выравнивание по 4 байтам. Мы занимаем две строки памяти нашей структурой, но вторая заполнена наполовину.

Что происходит в этом случае, так это то, что, если не указано иное, структура получает PACKED с дополнительными битами заполнения, чтобы заполнить строку памяти и исправить несоосность. Как уже упоминалось, это можно оставить компилятору, или мы можем указать, что мы собираемся упаковать нашу структуру с дополнительными данными. Последнее может быть полезно при работе с такими коммуникационными протоколами, как Modbus.

Что такое союз

Союз в языке C, иногда являющийся глупым братом Struct, имеет концептуально ту же цель, что и первый, но с немного другим применением.

Как и структура, объединение может определять новый тип данных. Однако, в отличие от структуры, объединение не будет занимать память для всех содержащихся в нем типов данных. Действительно, объединение будет занимать только место для большего типа данных в своем определении.

Например, объединение, содержащее 10 символов и 1 целое число, займет 4 байта.

Почему и для чего это нужно? Вы можете спросить, и ваш вопрос является законным. Дело в том, что объединение позволяет вам сэкономить место, и когда вы работаете с несколькими мегабайтами, даже сохранение пространства этих 10 символов приятно иметь.

Как же тогда использовать объединение? Простой пример можно найти в бинарных деревьях, где у каждого элемента есть левый и правый лист. Подумайте об этом, при прокрутке дерева такого типа вам нужно каждый раз читать и левый, и правый лист?
Ответ — нет, и здесь пригодится объединение, где я могу избежать копирования обоих листьев в каждый доступ.
В общем, объединение используется, когда не все его данные нужны одновременно.

Статичный и изменчивый

Это еще одна классика, которую вы не можете пропустить в интервью по разработке микропрограмм. Я чуть не обижаюсь, когда никто не приносит хотя бы одну из этих двух на стол.
Я много раз повторяла им, что буду петь их определение своим будущим детям, чтобы они заснули ( или им снятся кошмары ).

Volatile – это ключевое слово, используемое в языке C, чтобы сообщить компилятору, что не следует путаться с определенной переменной, которая была объявлена ​​с ним.

Иногда случается так, что у вас есть переменная, которая нигде в вашем коде не изменяется, но вы знаете, что она будет изменена из внешних ресурсов через протокол последовательной связи или другие.
В этом случае современные компиляторы хотели бы запустить оптимизацию для этого переменную, например, выбросить ее, поскольку она оказывается неиспользуемой.
Volatile предотвращает это и защищает вашу переменную от плохих ( или оптимальных) намерений компилятора. .

Static — еще одно ключевое слово C, которое необходимо знать, и по сравнению с volatile оно может показаться сложным, когда дело доходит до интервью. Static действительно имеет два разных значения, в зависимости от его положения в вашем коде.

При использовании для глобальных объявлений (глобальные переменные или прототипы функций) этот элемент становится видимым внутри файла, в котором он объявлен. Таким образом, статическая функция, объявленная в исходном файле .c, будет видна и доступна для вызова внутри самого файла и нигде больше. То же самое относится и к статической переменной.

Тем не менее, при использовании в локальной области видимости, например, для объявления переменной в функции, смысл больше не в отношении видимости, а в запоминании ее значения.

Статическая локальная переменная — это действительно переменная, которая не сбрасывается и не уничтожается в конце выполнения функции, более того, она сохраняет свое значение. Это означает, что переменная, объявленная статической, с начальным значением 0, которое увеличивается при каждом выполнении своей функции, при следующем вызове будет равна 1, затем 2, затем 3.

Управление памятью в C

Еще одна тема, которую вам могут задать, — это управление памятью в C, то есть то, как C развертывает ваш красивый код в памяти и что происходит со всеми этими неинициализированными и фиктивными переменными.

У нас есть 5 разделов для описания:

  1. Текстовый сегмент
    Содержит исполняемый код и размещается под областью кучи/стека во избежание переполнения. Это объявлено как совместно используемое и только для чтения.
  2. BSS
    Контейнер для неинициализированных данных, здесь мы можем найти все переменные, объявленные как статические или общие глобальные переменные, которым не было присвоено никакого значения во время объявления. Затем этот раздел должен быть взят из ядра операционной системы, которое должно инициализировать все эти переменные нулями, когда программа начинает свое выполнение.
    Да, чуть не забыл упомянуть, BSS означает Block. Начните с символов, и сейчас нетрудно понять, почему.
  3. Инициализированный сегмент данных
    Название говорит само за себя, как и BSS, но здесь данные были инициализированы разработчиком. Он не только для чтения, так как значения этих переменных могут измениться.
  4. Куча
    Вместе со стеком, который вы найдете в следующем пункте, куча занимает конечный участок памяти. Это делается для того, чтобы избежать того, что плохое программирование приведет к неправильному использованию и занятию всей памяти. Таким образом, куча и стек имеют общую область, где они растут в противоположных направлениях.
    Куча требуется для управления распределением динамической памяти, что означает все, что создается, распределяется или уничтожается с помощью malloc, calloc или бесплатно.
  5. Стек
    Наконец, стек, который находится в той же области кучи и растет в противоположном направлении, как упоминалось выше. Стек содержит все автоматические переменные из функций и получает новые данные, когда происходит вызов функции.
    Каждый вызов функции имеет в стеке кадр стека, содержащий его переменные, входы и обратный адрес. Обратите внимание, что я выделил *вызов полужирным шрифтом в предыдущем предложении, поскольку стековый фрейм — это понятие, относящееся не к функции, а к вызову. Это различие, которое может показаться неважным, делает рекурсию возможной в C (и такой мощной и эффективной).

Принципы операционной системы, процедура загрузки и многое другое.

К сожалению, этот пост не может охватить все, даже если бы я хотел, но моя жена — да, кто-то женился на мне — смотрит на меня испуганно, как долго я могу оставаться здесь и писать, не отводя глаз. экрана.

Пора выгуливать собаку, принимать душ, есть и делать все остальное, что делают люди, чтобы считать себя частью функционального общества.

Имея это в виду, позвольте мне перейти к концу этого поста с несколькими последними темами и деталями, которые могут оказаться полезными во время собеседования на должность инженера по прошивке. Я могу детализировать их в будущем посте.

Фантастическая ОС и где их найти

Основы операционных систем нельзя пропустить при подготовке к собеседованию на работу, где 90% вашего времени будет посвящено аппаратному обеспечению и драйверам.
Давайте посмотрим на несколько вопросов, которые интервьюеры любят спрашивать и на которые отвечают. им нравится слышать.

Что такое операционная система

Операционная система (далее ОС) — это программа, обеспечивающая контролируемый и простой доступ к ресурсам компьютера. Вот и все, с ОС мы можем печатать на клавиатуре, не зная битовой последовательности каждой буквы, мы можем использовать принтер для печати, USB для подключения жесткого диска и так далее.

Улучшая детализацию, ОС будет управлять такими компонентами, как память, ЦП, шина и всеми остальными компонентами, составляющими компьютерную систему.

Можно выделить 3 основных подхода к разработке ОС. Мы определим монолитную ОС с ядром, которое содержит все системные функции, такие как системные вызовы, драйверы, модули.
Modular мало чем отличается от предыдущий, но он состоит из нескольких модулей, которые можно присоединять и отсоединять с разной легкостью. Микроядро – это ОС, в которой ядро ​​содержит обязательные функции, но не содержит драйверов или других модулей. В идеале архитектура микроядра содержит менее 200 тысяч строк кода даже для самых сложных систем. .

Ядро

Я упоминал это слово в предыдущем разделе, но что это за ядро?

Ядро — это ядро ​​ОС, оно обеспечивает важные и обязательные функции, такие как планирование процессов, выделение памяти для выполняемых процессов, выделение памяти для хранения данных, доступ к периферийным устройствам и другие.

Ядро предоставляет системные вызовы, которые представляют собой функции, обеспечивающие прямой доступ к оборудованию и которые могут вызываться более высокими уровнями, такими как пользовательские приложения и драйверы.

Обзор загрузки

Давайте продолжим и посмотрим на загрузку, еще одну важную процедуру, которую могут задать во время собеседования с целью нанять инженера по прошивке.

Загрузка — это тема, которая сама по себе требует большего, чем раздел и даже больше, чем статья. Он огромен, и многие вещи можно рассмотреть и обсудить, но ради этого поста давайте остановимся на основном обзоре, который может спасти ваше интервью, когда придет время этого «У меня есть последний вопрос» приходит.

Прошивка, которая обеспечивает загрузку системы, обычно делится на 3 разных этапа:

  • Этап 1, Bootstrap
    Этот небольшой фрагмент кода имеет размер 440 Б и находится в первом секторе диска для загрузки. Он почти ничего не делает, если не несколько инициализаций и вызов следующего этапа, загрузочного сектора.
  • Этап 2, загрузочный сектор
    31 КБ кода и данных для хранения таблицы с несколькими флагами, среди которых наиболее важным является активный флаг, который отслеживает первый раздел для запуска и, следовательно, адрес следующего этапа для вызова.
  • Этап 3, Загрузчик конкретной ОС
    Этот этап находится непосредственно в разделе, содержащем загружаемую ОС. Он специфичен для каждой ОС и отныне управление будет вестись на него.
    Например, в Linux после этого шага процесс инициализации будет запущен с PID=1

Что здесь не описано

Опять же, невозможно охватить все темы в одном посте. Поэтому в этой статье чего-то не хватает, например, следующих тем:

  • Иерархия памяти и связанные темы (MMU, уровни кэша)
  • Общее управление памятью (сегментация, пейджинг, виртуальная память, подкачка)
  • Физическая структура памяти (MOSFET, линии памяти, проблемы с энергопотреблением, ограничения)
  • Обработка прерываний (вектор прерываний, ISR, маскированные прерывания)
  • Безопасность (TLS, функции шифрования, ARM TrustZone)

Выводы и личный опыт

Мы знали, что эта точка будет достигнута. Выводы всегда трудно напечатать из-за усталости пальца и из-за сложности писать о многих разных вещах в одном месте.

Поскольку многие советы даны в предыдущих разделах, не хватает одного: моего опыта.

У меня было несколько собеседований по разработке микропрограммного обеспечения в малых и крупных компаниях, и вот мои пять копеек на самые известные из них.

  • Qualcomm
    В то время это было легко. Они открывали новую площадку в Европе, создавали там первую команду, работающую не только на аппаратном обеспечении, и стремились к быстрому росту. Кроме того, вакансия предназначалась для инженера по валидации кремния, а не для разработки микропрограммы. Несколько вопросов о статических, энергозависимых и подсказках по обработке прерываний.
    Иногда ключом к успеху является удача.
  • Red Hat
    Тяжелое интервью. Может быть, один из самых сложных, которые я когда-либо делал. По какому-то нехорошему стечению обстоятельств мы были вынуждены сделать все за один день и за три часа подряд. Один за другим.
    В основном вопросы, касающиеся моего предыдущего опыта, и последнее техническое упражнение по виртуализации устройств в Linux. Честно говоря, это было больше об алгоритмах, чем о прошивке.
  • Intel
    У Intel много дружелюбных людей, когда дело доходит до интервью. Я прошел собеседование на должность инженера по программному обеспечению в команде, занимающейся разработкой ASIC и FPGA. Должность была связана с разработкой драйверов DDR, что-то совершенно новое для меня — всегда применяйте!. Интервью включало в себя несколько вопросов о C, подобных тому, который я обсуждал в предыдущих разделах, и несколько побитовых операций.
  • Apple
    Но это если у вас нет доброго менеджера по найму. Apple проводит первый раунд с менеджером по найму — то есть человеком, который будет вашим менеджером, если в конечном итоге будет принят на работу — а затем утомительный 6-часовой день, когда 6 разных сотрудников на разных уровнях обращаются к вам и задают вопросы.

Надеюсь, эта статья поможет вам на следующем собеседовании, для меня это был отличный способ освежить в памяти несколько тем в поисках следующей работы!