
再一次,我们弄清楚了如何不为微控制器编写固件。 上一篇文章引起了很多人的感动,在我看来,很少有人理解,也许对我来说,为什么所有这一切都开始的解释很少。
因此,我准备了一个示例 。
尽管这只是标准外设库中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++) { USART_SendData(USARTy, message[i]); GPIO_SetBits(GPIOC, GPIO_Pin_13); 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平台。