Como parar de escrever firmware para microcontroladores. Estamos começando a viver ...


E, novamente, descobrimos como não escrever firmware para microcontroladores. O artigo anterior despertou muitas emoções nas pessoas e, parece-me, poucas pessoas entenderam e, talvez, não me foi explicado por que tudo isso foi iniciado.


Por isso, preparei um exemplo .


Embora seja apenas uma amostra aprimorada de DMA_Polling da Biblioteca de Periféricos Padrão.


Mas esta é a vantagem dessa abordagem: você pode usar todos os desenvolvimentos do código executado no microcontrolador, incluindo bibliotecas do fabricante MK, como HAL ou Standard Peripherals Library. E isso deve ser justo para qualquer controlador que suporte openOCD - pelo menos STM32, Atmel, PIC32 e outros na lista . Ao mesmo tempo, podemos usar todas as bibliotecas do PC host, bem como os novos padrões de linguagem C ++. E se você escrever wrappers, em geral, poderá usar qualquer idioma. Mas não compliquei muito aqui. Eu apenas decidi mostrar as funcionalidades e recursos básicos.


No exemplo, é claro, piscaremos o LED. E também envie dados no UART e em outro UART para recebê-los usando o DMA. Usar o DMA oferece um bônus enorme. Muitas vezes, é possível livrar-se das interrupções que não podemos usar aqui e das pesquisas, que, devido ao meu depurador, são muito lentas, mas ainda menos tempo para capturar dados nas interfaces. E também gerar rapidamente. Portanto, é bastante simples criar um gerador de sinal programável e um sniffer de várias interfaces.


O equipamento no qual testaremos permanece desde o início do primeiro artigo


imagem
Aqui, conectei a fiação branca UART1 (pino PA9) com o Rx UART2 (pino PA3).


Se você olhar para o código
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 %d\n", strlen(message)); const uint16_t rec = DMA_GetCurrDataCounter(USARTz_Rx_DMA_Channel); printf("qty of received byte using DMA : %d\n", 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; } 

Você pode ver que, com a exceção da nossa função de converter endereços e funções da biblioteca padrão, todo o resto foi retirado pelo SPL do ST, em princípio era possível usar as funções HAL. Mas estou mais familiarizado com o bom e velho SPL.


Como montar e executar tudo


Este é um exemplo para um PC com Ubuntu 16.04 de 64 bits:


Primeiro você precisa baixar o Pintool v3.7


Descompactar é conveniente, então você pode definir a variável PIN_ROOT para criar o cliente PinTool ou simplesmente localizar nosso cliente em


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

Eu faço o segundo caminho


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

Em seguida, você precisa criar um cliente de 32 bits


 make TARGET=ia32 

O binário estará aqui obj-ia32 / addrIntercept.so. É necessário 32 bits, porque no ARM ortex esse tamanho de endereço.


Agora você pode coletar o próprio exemplo. Copio-o diretamente para a pasta no cliente 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 

E nós obtemos o binário no diretório test.elf. Para simplificar o experimento, colocarei o arquivo no diretório do nosso cliente Pintool AddressIntercept


Antes de começar tudo, precisaríamos criar FIFOs nomeados para se comunicar com o cliente OpenOCD


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

in.fifo out.fifo - nomes padrão para nossos clientes, você pode dar outros nomes, mas eles terão que ser especificados explicitamente ao iniciar clientes.


Vamos iniciar o cliente openOCD, no meu caso eu preciso passar o servidor ip openOCD para ele, será 192.168.0.111, a porta deixará o 6666 padrão, então não o especifico.


Então, corra em ordem


 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 

E a conclusão deve ser assim:


imagem


Espero um exemplo ilustrativo. Já é uma prova de conceito que pode ser usada.


E tudo deve funcionar, inclusive no MacOS e no Windows (aqui, você pode precisar ajustar o trabalho com o nome fifo ou substituí-lo pelo que está nas "janelas").


Além disso, nos artigos a seguir, se for interessante, você pode falar sobre o REPL como no GIF do artigo anterior e outras maneiras de interceptar endereços, sem limitar a plataforma Intel.

Source: https://habr.com/ru/post/pt434080/


All Articles