Uma ferramenta para debuggar bibliotecas de baixo-nível.
Suponha que estamos programando uma biblioteca para um sensor que descreve seu mapa de registradores internos da seguinte forma:
Endereço | Função |
---|---|
00 | [R/W] Modo de Operação |
02 | [R/W] FIFO de Entrada |
O 7º bit do endereço determina Escrita (1) ou Leitura (0)
Podemos então construir uma biblioteca, supondo que as funções bsp_*
são uma forma de isolar funções de HAL de um microcontrolador específico. Então nossa biblioteca é genérica para diferentes plataformas de hardware. Assim:
#include "target.h"
#include "bsp.h"
target_err_t target_init(target_t *target, void *const spi) {
target->mode = 0;
return TARGET_OK;
}
target_err_t target_set_config(target_t *target, const int config) {
char rx[1] = { 0 };
char data[1] = { (char)config };
bsp_transmit(MODE_REG | WRITE_MSK, data, 1, rx, 1);
return TARGET_OK;
}
target_err_t target_send_packet(target_t *target, char data[], int len) {
char rx[1] = { 0 };
while (len--) { bsp_transmit(TX_FIFO | WRITE_MSK, &data[len], 1, rx, 1); }
return TARGET_OK;
}
target_err_t target_get_mode(target_t *target, char *rx_buffer, int size) {
char data[] = { 0x00 };
bsp_transmit(MODE_REG, data, 1, rx_buffer, 1);
return TARGET_OK;
}
Então testariamos nossa biblioteca dessa forma:
target_t target;
target_init(&target, &gcomm);
target_set_config(&target, MODE_PADRAO);
char tx[] = { 0xAD, 0xDE };
target_send_packet(&target, tx, sizeof(tx));
char rx[1];
target_get_mode(&target, rx, 1);
printf("RX: %02X \n", (uint8_t)rx[0]);
Usando essa ferramenta de debugação é possivel rodar esse código no PC. Dado que possamos programar um mock do sensor, como:
comm_read(&comm, recv_buff, sizeof(recv_buff));
const uint8_t is_write = recv_buff[0] & WRITE_MSK;
const uint8_t address = recv_buff[0] & (~WRITE_MSK);
const int len = recv_buff[1];
if (address < sizeof(register_map)) {
if (is_write) {
printf("[WRITE] ADDR: %d\n", address);
memcpy(®ister_map[address], &recv_buff[2], len);
prinf_reg_map(register_map, sizeof(register_map));
} else {
printf("[READ] ADDR: %d\n", address);
memcpy(&tran_buff, ®ister_map[address], len);
}
}
comm_write(&comm, tran_buff, sizeof(tran_buff));
As funções comm_*
fazem a comunicação entre o processo da biblioteca ("microcontrolador") e o sensor. Mais detalhes no arquivo src/mock/target-mock.c
.
Executar o código então nos daria a saida:
[WRITE] ADDR: 0
Register Map:
F0 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
[WRITE] ADDR: 2
Register Map:
F0 00 DE 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
[WRITE] ADDR: 2
Register Map:
F0 00 AD 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
[READ] ADDR: 0
RX: F0
Teriamos um log da comunicação entre a biblioteca e o sensor. Então seria trivial encontrar erros de programação e diferenças do esperado pelo datasheet.