如何停止为微控制器编写固件。 我们开始生活...


再一次,我们弄清楚了如何不为微控制器编写固件。 上一篇文章引起了很多人的感动,在我看来,很少有人理解,也许对我来说,为什么所有这一切都开始的解释很少。


因此,我准备了一个示例


尽管这只是标准外设库中DMA_Polling的经过调整的示例。


但这是这种方法的优势,您可以使用微控制器上执行的代码的所有开发,包括制造商MK的库,例如HAL或标准外设库。 对于所有支持openOCD的控制器-至少是STM32,Atmel,PIC32和列表中的其他控制器,这应该是公平的。 同时,我们可以使用主机PC的所有库,也可以使用新的C ++语言标准。 而且,如果您编写包装器,则通常可以使用任何语言。 但是我在这里并没有复杂化。 我只是决定展示基本功能。


当然,在示例中,我们将使LED闪烁。 并且还在UART和另一个UART上发送数据以使用DMA接收数据。 使用DMA可带来巨大的好处。 通常,可以摆脱我们在这里无法使用的中断,并进行轮询,由于我的调试器,轮询非常慢,但是在接口上捕获数据的时间仍然更少。 并且还可以快速生成。 因此,制作可编程信号发生器和各种接口的嗅探器非常简单。


第一篇文章开始,我们将要测试的设备仍然存在


图片
在这里,我将白色接线UART1(PA9引脚)与Rx UART2(PA3引脚)连接在一起。


如果你看代码
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; } 

您可以看到,除了我们从标准库转换地址和函数的功能以外,其他所有内容都由ST的SPL承担,原则上可以从HAL函数中使用。 但是我对老式的SPL更为熟悉。


如何组装和运行所有这些


这是使用64位Ubuntu 16.04的PC的示例:


首先,您需要下载Pintool v3.7


解压缩很方便,您可以定义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位,因为在ARMortex中这样的地址大小。


现在,您可以收集示例本身。 我将其直接复制到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 

结论应该是这样的:


图片


我希望有一个说明性的例子。 已经可以使用的概念证明。


此外,一切都应该起作用,包括在MacOS和Windows上(在这里,您可能必须使用命名为fifo的作品进行调整或将其替换为“ windows”中的内容)。


此外,在接下来的文章中,如果有趣的话,您可以在前一篇文章中以GIF的形式谈论REPL,以及其他拦截地址的方式,而不会限制Intel平台。

Source: https://habr.com/ru/post/zh-CN434080/


All Articles