﻿# Качество встраиваемого ПО или погром всё\-таки случился

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


> Эта статья впервые была \[опубликована\]\(https://ko\.com\.ua/kachestvo\_vstraivaemogo\_po\_ili\_pogrom\_vsyo\-taki\_sluchilsya\_98518\) на сайте "\[Компьютерное Обозрение\]\(https://ko\.com\.ua/kachestvo\_vstraivaemogo\_po\_ili\_pogrom\_vsyo\-taki\_sluchilsya\_98518\)", перепечатана и переведена с разрешения редакции\\\.

Сразу предупреждаю \- текст будет не для слабонервных\. Это почти что Стивен Кинг\. Ужасы будут\. Ещё и какие\.

Итак, лет шесть назад две пожилые женщины в штате Оклахома поехали куда\-то на своей Toyota Camry и поездка их закончилась трагически \- одна из них погибла \(пассажир\), вторая получила тяжёлые травмы\.

Ситуация была усложнена почтенным возрастом потерпевших, что позволило затянуть судебные процессы на годы и списывать странное поведение машины на водителя \(которой просто не повезло, трудно представить себе почтенную пожилую даму, разгоняющую далеко не лёгкую и чтобы очень уж резвую Camry до привычных нашим владельцам этих диванно\-мягких колесниц, почему\-то считающихся у нас чуть ли не "спортивными", скоростей\)\.

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

Первоначальная реакция официальных представителей Toyota в судебном процессе была очевидной \- "иногда люди делают ошибки при управлении своими автомобилями"\.

Потом случилось ещё более неприятное \- Camry начали неоднократно проявлять норов и склонность к неуправляемому разгону\. Из\-за чего возникли сотни судебных исков\. Списать всё на возраст водителя уже не удавалось, и виновный был как будто найден, им оказался\.\.\. штатный коврик, который якобы поджимал педаль газа из\-за неправильных размеров и недостаточной эластичности\.

Всего на удовлетворение потока исков Toyota в прошлом \(2012\) году затратила более миллиарда долларов, некоторые иски в судах отдельных штатов были не удовлетворены, например, суд Калифорнии отклонил 20\-миллионный иск родственником водительницы Camry 2006 года выпуска, погибшей в результате неуправляемого внезапного разгона автомобиля\.

К расследованию странностей в поведении Camry были подключены специалисты NASA, изучавшие возможность потенциальных проблем в подсистеме управления акселерацией этого автомобиля на протяжении 10 месяцев\. Анализ группы специалистов NASA оказался в выводах непростым \(по ссылке \- [немаленький pdf\-файл](https://www.nhtsa.gov/staticfiles/nvs/pdf/nasa_report_execsum.pdf) отчёта группы NASA\):

Группа \[исследователей\] NESC идентифицировала два гипотетических сбоя контроллера заслонки ETSC\-i \(не связанных с неэлектронными причинами\.\.\.\), способных привести к внезапному ускорению автомобиля без генерации кодов диагностики \- специфические ошибки в определении положения педали газа и систематические программные ошибки в вычислителе контроллера акселерации, которые не выявляются системой мониторинга автомобиля\.\.\. Последний сценарий связан с открытием дроссельной заслонки без команды водителя и одновременным сохранением работоспособности систем непосредственного впрыска и зажигания\. Непосредственное доказательство того, что эти сбои привели к выявленным авариям, группой не получены, но это не означает, что из\-за них подобные аварии невозможны\.

И вот, наконец, история пришла к завершению \- 24 октября суд штата Оклахома признал Toyota ответственной за инцидент шестилетней давности с присуждением полуторамиллионного штрафа\. 

А специалисты в области embedded\-программирования по окончанию судебного процесса получили возможность открыть данные об экспертизе "прошивки" злополучного контроллера дроссельной заслонки\.

И данные оказались далёкими от утешительных\.

Итак, группа экспертов, информацию о которых можно легко отыскать на сайте "гуру embedded программирования" \(EmbeddedGurus\), после анализа firmware контроллера дроссельной заслонки пришла к выводу что \(даю дословный перевод\) "это позорный образец проектирования и разработки ПО"\.

В выводах \- общее низкое качество кода, наличие ошибок в нём, которые могут вызывать случайный разгон автомобиля, общая система контроля и обеспечения безопасности исполнения кода  организована по принципу "карточного домика", и, наконец, вердикт, к которому прислушались судьи \- ошибки в firmware стали причиной аварии с тяжёлыми последствиями\.

В ходе анализа злополучного контроллера экспертами были проверены и отклонены предположения Toyota, что ошибки являются следствием аппаратных сбоев в микроконтроллере NEC \(Renesas\) V850, а именно, в его интерфейсе с внешней памятью с контролем чётности\. Что неудивительно даже без экспертного анализа, потому как контроллеры Renesas \(некогда NEC\) \- в своём роде эталонные для автомобильной индустрии \(и не только\), и используются в неисчислимых количествах, о такой злополучной ошибке \(явно приводящей к порче памяти\) давным\-давно знал бы весь мир, она или была бы исправлена в кремнии, или хотя бы внесена производителем в Errata \(уточняющую документацию\)\.

Вот, собственно, как выглядит этот самый вычислитель, из\-за которого вся история, совершенно обычный встраиваемый компьютерчик, никакой rocket science, просто добротная плата с весьма традиционными для автомобильной индустрии компонентами \(самая большая микросхема \- тот самый NEC\-Renesas V850\):

![a0083_Embedded_Quality_ru/image1.png](https://import.viva64.com/docx/blog/a0083_Embedded_Quality_ru/image1.png)

Контроллер дроссельной заслонки, по идее, не самое страшное, что можно придумать\. По идее\. Он считывает положение педали \(или принимает его от другого контроллера по какой\-то бортовой сети вроде CAN или более развитой надстройки над CAN, FlexRay\)\. Если он сам считывает информацию, то выдаёт CAN\-датаграмму об этом прочим контроллерам, и, само собой, формирует управляющий сигнал шаговому двигателю заслонки\. Ещё он очевидно "завязан" в систему поддержания стабильной скорости \(круиз\-контроля\)\. Собственно, это всё\. Что подтверждается здоровенным прошлогодним тематическим документом от самой Toyota \([большой pdf\-файл](https://www.google.com.ua/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0CEQQFjAC&url=http%3A%2F%2Fpressroom.toyota.com%2Farticle_download.cfm%3Farticle_id%3D3597&ei=C8dvUpaWA5KxhAern4GYBw&usg=AFQjCNEy-ID0BgsyzhBqVoJ0PkCtTbkuXQ&sig2=_JQRtiqXyecpKoc-hddp1g&bvm=bv.55123115,d.ZG4&cad=rja), только для любителей hardcore подробностей, он интересен потому что демонстрирует прошлогодние объяснения\)\.

Ну а теперь держимся крепко за что можем держаться \- в firmware, решающем эту задачу, надстроенным над операционной системой реального времени, экспертиза выявила\.\.\. **одиннадцать тысяч глобальных переменных**\. Код реализации firmware назван хорошо знакомым всем программистам словом "**spaghetti**"\. Анализ цикломатической сложности программы выдал **67 не пригодных для тестирования функций**, а ключевая функция определения угла дроссельной заслонки в ходе этого анализа показала какую\-то удивительную оценку, при которой не только тестирование, но и вообще какое\-либо сопровождение программы невозможно\. Соблюдение отраслевого стандарта кодирования \(для автомобильной промышленности такой есть, даже целое семейство, совокупно называемое MISRA\) характеризуется выявленным числом его нарушений — их набралось **80 тысяч** \(в Toyota принят свой внутренний стандарт, который заимствует из MISRA всего 11 правил, при минимально требованных во время написания кода 93\-х\)\. По ходу дела было выявлено, что в такой сложной системе полностью отсутствует учёт сбоев и ошибок\. При всём этом великолепии все связанные с безопасностью функции контроллера в его "прошивке" оказались реализованными одним единственным процессом\. Тема отдельного разговора \- watchdog\. В "настольном" программировании это нечастое явление, в мире встраиваемых систем \- необходимая функция\. Watchdog или сторожевой таймер \- обычно внешнее по отношению к вычислителю устройство \(хоть бы и реализованное на одном с вычислителем кристалле\)\. Принцип его работы предельно прост \- если какой\-то процесс вовремя не сбросил ранее выставленный на какое\-то время страбатывания сторожевой таймер, последний вызовет аппаратное прерывание, оповещающее вычислитель, что с процессом что\-то явно не так, или вообще инициирующее быстрый системный сброс\. Использование watchdog в "прошивке" вызвало большие сомнения у экспертов \- подконтрольным сторожевому таймеру в этой системе оказался по сути только процесс, обслуживающий редкие прерывания системного таймера, что означает \- любой сбой в обработчике прочих прерываний мог приводить к исполнению неизвестно чего примерно\.\.\. полторы секунды до сброса вычислителя от сторожевого таймера\. И эксперты не взялись утверждать, что эти полторы секунды до сброса гарантированы, они не исключили возможности, что сброс вообще не наступит\. Напоследок не менее прекрасное \- коды возврата большинства вызовов RTOS, которые предназначены для сообщений об ошибках, в "прошивке" вообще игнорируются\.

Дальше начинается архитектурное\. Не менее красивое\. Основной вычислитель \(неповинно обвинённый в грехах NEC\-Renesas V850\) мониторится дополнительным микроконтроллером с "прошивкой" от стороннего производителя, которая выходит за границы ответственности Toyota\. Да, это хорошо, когда есть независимый мониторинг\. Но каким образом единственный аналогово\-цифровой преобразователь, который как раз и предназначен для считывания аналогового сигнала положения педали газа оказался мало что не зарезервированным \(продублированным\), но ещё и интегрированным именно в этот второй микроконтроллер \- это даже трудно сказать кто такое придумал\. Точности\-то от такого преобразователя нужно всего ничего \(ну какая может быть прецизионность в нажатии на педаль газа\), АЦП такого класса совершенно копеечные и прекрасно отработаны, и вот такая экономия, формирующая потенциально сверхопасную "точку критического сбоя" \(single point of failure\)\. Изящное решение оказалось адекватно поддержанным на уровне кода \- отказоустойчивый код сопроцессора\-монитора оказался зависимым от неназванной из принципов соблюдения промышленных секретов функции, выполняемой основным микроконтроллером, причём на эту одну функцию взвалили кучу всего \- от преобразования угла педали в угол дроссельной заслонки до управления в режиме круиз\-контроль и даже до диагностики\.

Прямо скажу \- когда я читал оригинальные статьи и дошёл до одиннадцати тысяч глобальных переменных, используемых в системе реального времени, где любое лишнее находящееся в общем для всех процессов доступе состояние \- уже большая проблема, мне стало как\-то не по себе\. И потому хочу ещё раз напомнить, о чём писал в прошлый раз\.

Без сомнения, этот странный код для Toyota писали не школьники и не студенты\. И проектировали вычислитель, оказавшийся тоже весьма загадочной архитектуры, вовсе не профаны\. Без сомнения и слава богу, что вроде как это не во всех моделях машин такое, что всё это выявлено и локализовано, что в Toyota после такого кошмара \(есть такие специально обученные люди, занимающиеся репутационным менеджментом, так вот я им, которые из Toyota, очень не завидую\) всерьёз улучшат разработку и тестирование firmware\.

Но этот наглядный пример в контексте рвущегося в ширь и ввысь IoT \(Internet of Things\) надо бы не забывать\. Надеюсь, что индустрия его не проигнорирует\. Уже не получится\. Потому что шум поднялся на весь мир\.

Откланиваюсь\.