- PVSM.RU - https://www.pvsm.ru -

Как перестать писать прошивки для микроконтроллеров. Пример

Как перестать писать прошивки для микроконтроллеров. Пример - 1

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

Поэтому подготовил пример [1].

Хотя это всего лишь подправленный сэмпл DMA_Polling из Standard Peripherals Library.

Но в этом и преимущество такого подхода, что можно использовать все наработки из кода выполняемого на микроконтроллере, в том числе и библиотеки от производителя МК типа HAL или Standard Peripherals Library. И это должно справедливо быть для любого контроллера, который поддерживает openOCD — хоть STM32, Atmel, PIC32 и прочие по списку [2]. При этом мы можем использовать все библиотеки хостового ПК, а так же пользоваться новыми стандартами языка С++. А если написать обертки, то и вообще можно использовать любой язык. Но я не стал сильно усложнять здесь. Просто решил показать основной функционал и возможности.

В примере, конечно, будем моргать светодиодиком. А так же отсылать данные по UART и по другому UART их принимать с помощью DMA. Использование DMA дает громадный бонус. Зачастую можно будет избавиться от прерываний, которые мы здесь не можем использовать, и поллинга, который из-за моего отладчика работает очень медленно, но тем неменее успевать захватывать данные на интерфейсах. А так же быстро генерировать. Поэтому довольно просто сделать программируемый генератор сигналов и сниффер разнообразных интерфейсов.

Оборудование на котором будем испытывать, осталось со времен первой статьи [3]

image
Здесь белым проводком соединил Тх UART1 (PA9 pin) c Rx UART2 (PA3 pin).

Если посмотреть на код

const char * message = "AddressIntercept PinTool UART DMA example";
int main()
{
  sizeMemoryTranslate_t s = 0;
  memoryTranslate *p = getMemoryMap(&s);

  pAddrPERIPH = p[0].start_addr;
  pAddrSRAM = p[1].start_addr;

  init();

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  GPIO_InitTypeDef gpio;
  gpio.GPIO_Pin = GPIO_Pin_13;
  gpio.GPIO_Speed = GPIO_Speed_50MHz;
  gpio.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &gpio);

  const size_t _SIZE_MESSAGE = strlen(message);

  printf("sending message ");
  for (int i = 0; i < _SIZE_MESSAGE; i++) {
    /* Send one byte from USARTy to USARTz */
    USART_SendData(USARTy, message[i]);
    GPIO_SetBits(GPIOC, GPIO_Pin_13);
    /* Loop until USARTy DR register is empty */
    while (USART_GetFlagStatus(USARTy, USART_FLAG_TXE) == RESET);
    printf(".");
    fflush(stdout);
    GPIO_ResetBits(GPIOC, GPIO_Pin_13);
  }
  printf("n");
  printf("qty of sent bytes %dn", strlen(message));

  const uint16_t rec = DMA_GetCurrDataCounter(USARTz_Rx_DMA_Channel);
  printf("qty of received byte using DMA : %dn", sizeDMAbuf - rec);
  printf("read message from buffer DMA : ");
  const uint8_t *pM = (uint8_t *)pAddrSRAM;
  for (int r = 0; r < _SIZE_MESSAGE; r++) {
    printf("%c", pM[r]);
    fflush(stdout);
  }
  printf("n");
  assert(strncmp(message, (const char *)pM, _SIZE_MESSAGE) == 0);
  printf("Received and sent bytes are equal!n");
  return 0;
}

То можно увидеть, что за исключением нашей ф-ции преобразования адресов и ф-ций из стандратной библиотеки, все остальное взято SPL от ST, впринципе можно было и из HAL ф-ции использовать. Но мне привычнее старый добрый SPL.

Как это все собрать и запустить

Это пример для ПК с Ubuntu 16.04 64-bit:

Для начала нужно скачать Pintool v3.7 [4]

Распаковать куда удобно, дальше можно либо переменную PIN_ROOT определить для сборки PinTool клиента либо просто расположить наш клиент в

pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/

Я делаю вторым способом

cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/
git clone git@github.com:ser-mk/AddressIntercept.git
cd AddressIntercept

Дальше потребуется собрать 32-битный клиент

make TARGET=ia32

Бинарник будет лежать здесь obj-ia32/addrIntercept.so. 32-битный требуется, потому как в ARM Сortex такой размер адреса.

Теперь можно собирать и сам пример. Его копирую прям в папку к pintool клиенту

cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/AddressIntercept
Git clone https://github.com/ser-mk/addrIntercept-example-UART-DMA
Cd addrIntercept-example-UART-DMA
Make

И получаем в катологе test.elf бинарник. Дальше для простоты эксперимента, положу файл в директорию нашего Pintool клиента AddressIntercept

Перед тем что бы все запускать, нам надо бы создать именованные FIFO для общения с OpenOCD клиентом

cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/AddressIntercept
mkfifo in.fifo out.fifo

in.fifo out.fifo — названия по умолчанию для наших клиентов, можно дать и другие названия, но тогда их придется указывать явно при запуске клиентов.

Запустим openOCD клиент, в моем случае ему надо передать ip openOCDсервера, это будет 192.168.0.111, порт оставил стандартный 6666, поэтому не указываю его.

Итак запускаем по порядку

cd pin-3.7-97619-g0d0c92f4f-gcc-linux/source/tools/AddressIntercept
python3.5m OCDclient.py -ip 192.168.0.111 &
../../../pin   -t obj-ia32/addrIntercept.so -- addrIntercept-example-UART-DMA/test.elf

И вывод должен быть такой:

image

Надеюсь пример наглядный. Уже вполне получился proof of concept, который можно использовать.

Причем должно все работать в том числе на MacOS и Windows (здесь, возможно, придется подправить работу с named fifo или её заменить на то что есть в "окнах").

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

Автор: ser-mk

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/stm32/303438

Ссылки в тексте:

[1] пример: https://github.com/ser-mk/addrIntercept-example-UART-DMA

[2] списку: http://openocd.org/

[3] первой статьи: https://habr.com/post/402233/

[4] Pintool v3.7: https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.7-97619-g0d0c92f4f-gcc-linux.tar.gz

[5] Источник: https://habr.com/post/434080/?utm_campaign=434080