SimBank або 200 SmartCard в одній коробці

Як я вже писав у своєму першому топіку на Хабре про створення друкованої плати, моя фірма займається розробкою пристроїв для телефонії різного роду VoIP-, GSM-, PBX-шлюзів, розетки-ребутеры керовані через GSM та інше. Сьогодні я опишу процес розробки прошивки для пристрою SimBank в його PCI версії, де я виступив в ролі розробника схеми для ПЛІС.

Історія постановки завдання від керівництва історія роботи пристрою
Пристрій SimBank призначене для роботи з SIM (Subscriber Identification Module — модуль ідентифікації абонента) картою. Дані карти є різновидом ISO-7816 карт.

На Хабре є статті описують устройстви і принцип роботи зі смарт-картами.
Короткий вступ в SIM-карти OgreSwamp
Смарт-карти для самих маленьких brake
Як влаштована смарт-карта rlepricon
Я їх всі з задоволенням прочитав перед початком розробки. І повторювати написане в них не буду.


Пристрій SimBank

Саме пристрій було зроблено на фірмі вже давно і вдало використовувалося протягом декількох років. Але особливістю всіх PCI пристроїв на фірмі було навчальний PCI ядро, «яка поставлялася як є і претензії не приймалися». Вони і не виставлялися. З мінімальними переробками це ядро ставилося на всі без винятку плати. Це дозволяло зі знанням справи використовувати доступне адресний простір. З одним і тим же Vendor ID, Device ID, Class Code. Так як пристрої зазвичай збираються на фірмі і перевіряються на працездатність, конфліктів не виникало. В умовах обмежених часових рамок принцип «працює — не чіпай» досить доречний. Так тривало до якихось пір поки на деяких сучасних материнських платах не стали проявлятися нестабільність в роботі або взагалі плата не хотіла заводиться.
Прийшла пора більш ретельно розібратися з ядром PCI. Навчальний ядро доопрацьоване під свої завдання було документовано коментарями, але їх не завжди було достатньо. Посилання на місце, звідки воно було взяте, датована 2002 чи 2004 роком — не працювала.
Задача проста як день: «Пристрій має працювати на всіх стандартних платах».
В якості бонусу: «Навіть якщо це будуть не всі 200 SIM карт, а 196 або 1хх».
До цього моменту я ніколи не працював ні з SIM картами, ні з шиною PCI в якості розробника ПЛІС. Тільки схема та плата. Досвід розробки на VHDL і Verilog вже був.
Розбирання вирішено було почати з PCI, так як частина відноситься до SIM карт працювала.
Перше прочитання специфікації «PCI Local Bus» не подіяло чудесним чином і не сильно пролило світло на те як все треба робити. Начитавшись статей про те, як робити і як не робити я так толком нічого і не зрозумівши, вирішив: «треба робити, по ходу справи розберуся».
Для PCI у Altera в середовищі Quartus є Мегафункция, яка дозволяє генерувати ядро PCI з необхідними нам параметрами. До ядра додається хороша документація, на сайті є опис PCI-кита, до якого додається PCI модель, для поведінкового моделювання в ModelsSim-Altera. Все це разом — здорово допомагає освоїться з нуля в цій темі.
Altera дозволяє користуватися своїм Vendor ID (1172h).
У специфікації PCI обраний клас пристрою не доступний у версіях специфікацій: 07h — Simple Communication Controllers, 05h — Smart Card.
Далі все повинно працювати в Linux. Так як у колеги більше досвіду роботи з SIM-картами і з PCI, то з нього технічні вимоги. За що йому величезне спасибі. Грамотно складений документ, це половина справи. Хоч і вимагає «зайвої писанини».

Вивчення матеріалу
Так як пристрій розробляв не я, то мені необхідно було ознайомитися з проектом схеми та плати.
Схемна частина необхідна для розуміння, звідки йде і до чого приєднується, а плата дає зрозуміти куди вставляти програматор, SIM карти і де знаходиться та чи інша службова індикація. Про те як це зіграло злий жарт зі мною я опишу трохи пізніше.



За схемою ми маємо плату з двома ПЛІС Altera Cyclone II EP2C35672C8 в корпусі з 672 контактами. Одна ПЛІС приєднана до шині PCI і вона ж керує другий ПЛІС. До кожної ПЛІС приєднані по 100 власників SIM карт. До кожної SIM карті підведений свій сигнал скидання і даних, сигнал CLK йде на групу з 10 карт.



Кожна мікросхема EP2C35 містить 105 M4K блоків внутрішньої пам'яті. Всього в блоці RAM (включаючи біт парності) 4,608 біт.

Блоки підтримують різні конфігурації від 4K × 1 до 128 × 32(36).

Після цього вже мною був написаний документ із додатковими запитаннями, що за чим буде подаватися, хто стежить за тривалістю тих чи інших сигналів. Хто вважає правильність приходу даних від SIM та інше.

Розібравшись з контактами першої від шини PCI мікросхеми, я зробив пробний проект ядра PCI в Quartus, який мав запрацювати з новими параметрами на шині. Без будь-якої логіки — просто ядро.
Отримавши відповідь на команду «lspci-vv» моєму щастю не було меж.



Обговоривши з розробником драйвера і прикладної програми подальший хід роботи, ми зробили пробний проект в яких драйвер записував в пам'ять дані, а потім їх прочитував і звіряв. Спочатку перевірка робилася тільки за першою схемою мікросхемі.
Далі був розбір з другої мікросхемою.
Між двома мікросхемами на схемі передбачено 36 сигнальних ліній + 2 лінії між виходами PLL_OUT і CLK. У попередньому проекті використовувалися 19 ліній адреси і два байти на обмін даними (по одному в кожну сторону) сигнали читання і сигнал запису. Це було зроблено виходячи з специфіки роботи наявного ядра. І для отримання універсальності драйверів і програм. Так наприклад є усталена частина адрес звідки можна вичитати службову інформацію.
У ARM весриях зберігається інформація типу



Elgato G4_1 — тип пристрою (для PCI плат «K16» або «К32», для Симбанка — «SimBank»)
SIM51215 (SIM900 або інший) — тип встановленого GSM або 3G модуля (необхідний для вибору набір AT-команд). До описуваного пристрою має відношення в плані яку SIM-карту ми можемо через даний модуль вивести в мережу оператора.
2014 — рік розробки
ver.14.144 — номер версії прошивки
SN: 0123

І якщо перед прошивкою її не забули змінити на правильну, то за цими даними можна дізнатися багато цікавого з «амбарной книги», де записано під кого робився проект і які відмінності від стандарту забажав замовник.
Для Симбанка досить серійного номера. Так як конструктивно плата Симбанка завжди одна в пристрої. І в PCI версії така плата одна на фірмі.

Хворобливе рішення
У попередній версії ядра використовувалися два BAR. BAR1 c відображенням в пам'ять розміром 1М, BAR0 як регістри вводу виводу розміром 4К. Всі адресний простір віддавалася під обидві ПЛІС одночасно.
Від застосування IO вирішено було відмовитися з різних причин. По перше розробнику драйвера працювати з пам'яттю набагато простіше. По-друге, в мережі є безліч рекомендацій чому при можливості варто відмовитися від IO в нових розробках. По-третє, кількість IO ресурсів доступне для установки в ядрі від Altera обмежена 256. Ресурсів пам'яті можна виділити набагато більше. Але цей перехід спричинив за собою зміну роботи з модулями SIM карт. І означав майже повну переробку модуля обміну з SIM. До того відхід від звичної адресації означав, що ми не зможемо прочитати будь-своєю програмою в звичному місці потрібні нам битики.
Можна було не робити на два базових адреси і обійтися одним. Не економити один тактовий сигнал при обміні з картами першої мікросхеми. Це частина обміну даними не займається передачею голосу і нам не потрібно економити мілісекунди для того щоб отримати затримку не більше 20 мс. Але таке мені здалося правильним.

Структура
Після перших успіхів і перевірки запису в пам'ять тестових даних настав час вибудувати структуру обміну даними з SIM картами. Приблизне уявлення як треба буде робити у мене було давно, але після тестів я готовий був припустити, що воно буде працювати. І тести виконані були продумані і виконані не дарма.
Існуючих 36 + 2 сигнальних ліній не вистачало для того, щоб транслювати службові сигнали шини PCI на другу мікросхему без змін, а обмежувати прийом — передачу одним або двома байтами мені не хотілося. Навіть якщо вдасться рознести шину адреси і даних.
Тому 32 з 36 сигнальних ліній відразу ж були віддані на шину даних (адреси), 1 сигнальна лінія керувала загальним скиданням системи, а на інші три гуляємо вішаємо все управління. Для передачі сигналу CLK у нас була окрема лінія.
Режим мовчання, режим передачі адреси, режим запису одиночних даних, потокових даних (Burst), режими запису по масці, читання і потокове читання. Всього вісім станів шини які вклалися у три сигнальних лінії.
Залишилося тільки передати чотири сигналу BE для запису по масці. Їх було вирішено заховати в старші чотири біта на шині даних якщо у нас використовується такий режим.

Для кожної SIM карти в ПЛІС був виділений максимально можливий буфер. Так як зі Smart карткою здійснюється однопроводний напівдуплексний інтерфейс, карт у нас 100, а комірок пам'яті в мікросхемі всього 105, то й буфер вирішено було зробити один на прийом і передачу. І обнуляти адресацію при початку передачі або прийому. Мені пощастило і згідно стандарту від SIM карти не може прийти більше 256 байт даних за одну команду. А значить доступний буфер не переповниться поки ми його не віднімаємо.
Термін «команда» тут трохи відрізняється від стандарту ISO-7816. Там під командою розуміється звернення до карти, потім підтвердження від картки, а потім дані. Але мене цікавить кількість даних від обнулення до обнулення буфера.

Буфер для обміну даними з другої мікросхемою вирішено було не робити, а зробити безпосередній запис в пам'ять SIM карт у другій мікросхеми. Так як у мене вже було зайнято 102 блоку пам'яті з 105. Вибір першої і другої мікросхеми вибирається через звернення до BAR0 або BAR1 відповідно.
Для BAR0 і BAR1 зроблені різні контролери. Звернення до другої мікросхемі відбувається на такт пізніше, але це регулюється затримкою виставлення сигналу TRDY на стороні шини PCI.

Для кожної мікросхеми виділено 64ДО пам'яті, чого достатньо для обслуговування 128 Smart карт. У нас 100. Залишається ще 28 блоків. У двох блоках розмістимо службову інформацію де буде зберігатися інформація про стан скидання карти, швидкості обміну. Назад нам потрібно повертати кількість прийнятих даних від SIMки.

Далі все це потрібно змусити працювати і налагодити. Так як проект для 100 SIM карт компілюється дуже довго, та й 100 SIM карт спалити набагато дорожче ніж 1 або 10 вирішено налагодити обмін відразу на 1 — 5 картах, а потім вже додавати всі інші. Причому зробити налагодження лише першої половини, а вже коли вирішимо, що тут все вийшло, йдемо в другу мікросхему.
І тут мене чекав сюрприз.
Є схема, на якій контакти карт пронумеровані від 1 до 100. Є проект плати з якого вдало імпортовані налаштування контактів ПЛІС (PCI працює, тестовий запис в пам'ять працює, обмін між мікросхемами також працює). Проект зібраний для 5 карт, щоб якщо помилюся з початком нумерації від 0 або 1, то друга карта б заробила. Дудки.
Ну нічого, у нас є 10 світлодіодів на платі. І хоч ними я збирався займатися потім, довелося потім підсунути трішки ближче до зараз. Додаємо просту річ на включення/вимикання світлодіода, а лампочка не горить світлодіод не блимає.
Беремо осцилограф. CLOCK є, а скидання немає. Даних теж немає.
Імпорт даних підкачав? Звіряємо схему з платою, плату та схему з Pin Planner в Quartus. Збігаються. А скидання немає.
І ось тут мені на допомогу приходить старший товариш. І каже, що «принцеса в іншому замку» у програмі «SIM0» знаходиться з іншого боку коробки. І завжди так було.
Сюди можна заскріншотіть шматок з PCB проекту в P-CAD. Там є підписи сигналів

На платі це SIM 199, а у проекті SIM0. Проект складений лише для 5 карток. (Для 100 він просто ще не влазить). І тому решта 95 карт просто не обслуговуються. І для них навіть буфер пам'яті в ПЛІС не формується.

Для того щоб заощадити ресурси вирішено було тактувати блоки пам'яті частотою на якій працюють SIM карти. Так менше потрібно буде дільників. А з меншою частотою легше буде влізти в швидкісні ресурси мікросхеми. При цьому планувалося в буфер для SIM карти писати на швидкості шини PCI (33 МГц), а зчитувати на швидкості роботи з SIM-картами. З-за обмежень на реалізацію двухпортовой пам'яті в Cyclone II довелося шукати інші рішення. В підсумку самим простим і правильним виявилося тактувати всі блоки частотою 33 МГц від PCI_CLK. А зменшення кількості багаторозрядних лічильників довелося зробити шляхом сигналів дозволу для тактирования регістрів. До того ж такий підхід дозволив простіше писати тимчасові обмеження для TimingAnalyzer використовуючи multycycle.

Настроювання моделі. Для успішного завершення всіх винаходів нам потрібна модель. Для PCI ядра модель надає Altera. Для Smart карт довелося писати модель самостійно.
Мінус такого рішення, якщо я неправильно розумію як повинна працювати SIM карта, то я так само неправильно напишу модель. Але все обійшлося. Правда не відразу.
Моделювання дозволило на перших парах не сильно відволікати колегу, хоча потім на етапі налагодження в залозі нам довелося добряче розбиратися. Що не так в моделі, і як воно має бути.

T0/T1 чи не потрібно робити як краще, робіть як правильно
Спочатку в автоматі роботи з SIM картою відлагоджувати робота по скиданню і читання з SIM карти ATR, зміна швидкості і передача простий команди «A0 A4 00 00 02» і на все це потрібно було отримати відповідь «A4». Мені хотілося зробити автомат який би по включенню живлення сам би все прочитував і до моменту завантаження ОС працював з SIM картою на максимальній для неї швидкості. Це б дозволило розвантажити програму ініціалізації двісті(200!) SIM карт під час старту.
З деякими SIM картами все чудово пройшло, а дехто вперто віддавали h'3B й мовчали. В результаті спрацьовував таймер в автоматі і я скидав SIM карту.Так як вона не сказала мені на якій швидкості з нею можна поговорити. Якщо ж я отримував три або більше трьох байт, то я вважав що ATR лічений і можна працювати далі. Хоча на моделі все було чудово, але як виявилося у різних SIM карт по різному видаються ATR. Одні видають всю інформацію відразу, а у інших після відправки заголовка h'3B проходить пауза, а потім видається вся інформація. Збільшення паузи вирішив цю проблему. До пори До часу. Деякі SIM карти видають завершальний біт з такою ж великою паузою як і на початку після байта h'3B.
Вирішено. Ніяких розумних автоматів, мимовільних перемикань швидкості та іншого. Нехай про це думає процесор. Приймає рішення коли видати скидання, прибрати його, і нехай вважає коли порція даних від карти завершена.
Але є проблема. Ми ще не налаштували все плюшки, а у нас влазить все 80-85 SIM карт з необхідних 100 в кожній мікросхемі. Нехай це робить драйвер операційної системи. Йому не важко, а нам просторіше.
Далі пішла налагодження роботи з іншими командами вже одержуваними від драйвера з ОС. Налагодження на великій кількості SIM карт. І нові «відкриття».

197 з 200
Як вирішити якщо 197 з 200 карт працюють, а три ні то це точна робота чи ні? Відпрацювання велася на заблокованих оператором SIM картах, які ще відповідали на скидання і робили вигляд, що записують в себе SMS. Може три карти заблоковані не даремно і це вони помиляються? Як я був наївний.
Перша ж робота в реальному режимі показала, що з їхнього боку все вірно. Шукай.
І я знайшов. Не відразу. Допоміг мій колега який організував логи обміну по всьому SIM карт. виявилося, що іноді при запису великих команд у мене перескакував лічильник. І я два рази писав один байт в середині довгої передачі. Так як поведінкове моделювання справа довгий, то довгі команди в моделі я не використовував. Обмежувався короткими транзакціями. Робив усічені розміри лічильників. Зробив крок, змоделював, перевірив, запрацювало. Маленько «Ура!» і далі продовжимо. Записали байт, слово, подвійне слово. Пройшли пару адрес — значить і далі все буде добре.
І ось, на маленькій моделі все чудово, а в житті не працює. При цьому до моменту помилки SIM карта встигає віддати свій номер (якщо він записаний в карті), ICCID, IMSI і щось ще. А при імітації запису/читання в SIM-карту. Не завжди, лише з трьома з двохсот карток відбуваються помилки.
Ручне порівняння лода програми і логічного аналізатора показало, що помилка відбувається в тілі SMS-повідомлення. При цьому 197 карт пропускають цю помилку крізь пальці підрахунок CRC. Навіщо напружуватися для якихось SMS, а три карти таки дочекалися свого зоряного часу.
Я допрацював модель запустив, а на неї знову все в порядку. Як так?
Запускаю модель з повною перевіркою лічильників (Ділимо 33 МГц на 6, потім на 372, а потім ще і ще, замість умовно поділимо на 4, а потім ще на 16). Запусках ввечері модель, в надії вранці все побачити…
І вранці застаємо свою ОС сплячої, дитячим сном. У неї вимикався екран в режим енергозбереження. Але спати у нас з нею не доходило. Після 4+ годин моделювання понад 300 сигналів і шин, вона заснула «не роззуваючись». І вранці завівся з третього разу. Яка це радість, що мені не довелося відновлювати всю систему.
День роботи, відключення сну. І вже на наступний ранок я зміг знайти помилку. Правда перед цим цілий день у мене пішов на розборки з усякими іншими премудростями. І вранці щасливого дня я вже здогадувався помилку де шукати.
Вона не була останньою, були й інші більш явні і легкі в плані видобутку помилки.

Збираємо мозайку
Зробивши припущення про те, що робота зі Smart Card стабільна, я підключив другу мікросхему. Спочатку в проекті. Потім на моделі. Потім в залозі. Не все одразу, але і цю частину ми побороли. Як перевірити, що всі 200 місць працюють одночасно і не заважають сусідам? Де взяти стільки SIM карт? Знайшлися по засіках 200 штук. Запустилися.
Запустилися, віддали банк на перевірку. І ось ще один сюрприз. Якщо в SimBank зайняті всі місця, то все добре. Карти працюють стабільно, скидаються не часто. А якщо частина карт не встановлена, то на їхні місця приходить періодичний скидання. Але іноді скидання приходить на симетричні карти сусідній ПЛІС. Чому?
Відповідь на це питання я досі толком не знаю. Але зате я тепер знаю, що таке Signal Tap Logic II Analyser в Quartus від Altera. З допомогою нього вийшло через JTAG витягнути стану сигналів на шині PCI. Змінюючи проект і створюючи нові сигнали для старту відліку або стопа вдалося переглянути деякі частини всередині ПЛІС. Так я наприклад з подивом дізнався, що при читанні або запису більше восьми байт у мене майже ніколи не включається режим Burst. По запису взагалі ніколи, а при читанні не більше двох тактів PCI. Хоча з програми приходить команда «вважати 40 байт», а зчитування йде по чотири байти. З виставлення адреси на PCI



Проблему скидів частково вдалося вирішити програмно з боку драйвера, Частково обмеженням не використовувати непарна кількість SIM карток в банку до кращих часів.

Питання до аудиторії: чи є в Linux (Centos 6 32-біт) можливість писати всі логи звернення пристрою? Бажано при цьому не порушувати роботи шини PCI. Так щоб можна було задати Vendor ID/Device ID і зберігати його логи звернень R/W на шині?

Підсумок
У підсумку до закінчення всіх поліпшень повний проект в ПЛІС витрачає 89% логічних елементів і 85% доступною внутрішньої пам'яті. Все влізло, а це означає, що елементарна база та структура проекту обрані вірно.
За схемою зекономлено два 50 МГц генератора, так як в проекті береться тільки тактовий сигнал PCI 33 МГц, вони не використовуються і надалі можуть не встановлюватися на плату. Проект працює з усіма «подсунутыми» на сьогоднішній день материнськими платами.
Пристрій може реєструвати всі карти в мережі одночасно, лише б вистачило GSM каналів.

Зараз крім оновлення прошивок і драйверів у замовників кілька пристроїв працюють у нас. Одні відправляють SMS для проекту SprintSMS. Інші знаходяться «під охороною» нашої технічної підтримки і трудяться на благо замовника. Це дозволило зрозуміти суть роботи замовника, і що йому насправді потрібно. Як в плані ергономіки роботи так і в плані додаткового функціоналу програмного забезпечення. До того ж стабільно працюючий пристрій (тук-тук-тук, щоб не наврочити) дозволило більш якісно налагоджувати програмне забезпечення.

Але це вже інша історія.

Дякую всім.
Читачам за проявлений інтерес до статті. Авторам інших статей — за корисні уроки. Творцям Хабра за Хабр. Колегам за допомогу у важкі хвилини і «наданий» досвід. Керівнику — за розуміння.

P.S. В якості бонусу картинка з веб-інтерфейсу візуального контролю за роботою SimBankа.
Окреме спасибі за нього Максиму.


Тут SimBnak запущений в режимі на 100 карт.


Список карт з вичитала інформацією з них. На картах які вимагають введення PIN-коду частина інформації не доступна.


Web-інтерфейс доступний і з смартофна.
Виділені жовтим карти які зараз у роботі.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.