Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Log activity of the aemlic v2 board
/**
* aemlicLogger.c
* Copyright (c) 2022 Ken Webb
* MIT license
* based on ~/pico/ksw-examples/program/flash_program.c
*
* Log activity of the aemlic v2 board.
* Record how many seconds the Pico runs, each time it's powered up.
* This will give a rough idea of what the aemlic is doing.
*
* Linux command line:
* export PICO_SDK_PATH=/home/pi/pico/pico-sdk
* minicom -b 115200 -o -D /dev/serial0
* openocd -f interface/raspberrypi-swd.cfg -f target/rp2040.cfg -c "program aemlicLogger.elf verify reset exit"
*/
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/flash.h" // ~/pico/pico-sdk/src/rp2_common/hardware_flash/include/hardware
//#include "hardware/adc.h" // I may need this later?
// Erase and reprogram a region 256k from the start of flash.
// Once done, we can access this at XIP_BASE + 256k.
#define FLASH_TARGET_OFFSET (256 * 1024)
#define SLEEP_MS_ON 100 // 500 is default, 1000 100 900
#define SLEEP_MS_OFF 900 // 500 is default, 1000 900 100
#define SLEEP_MS_DEBOUNCE 2000 // debounce while connecting Pico to power
#define DO_DEBUG 0 // 1 or 0
const uint8_t *flash_target_contents =
(const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET);
uint16_t counter = 0; // count number of seconds that the Pico is alive
// initial values for data index High/Low
// these are dynamically updated each time the program runs
// - by searching from start of count_data
int dataIxH = 0;
int dataIxL = 1;
uint8_t count_data[FLASH_PAGE_SIZE];
void print_buf(const uint8_t *buf, size_t len) {
//size_t len1lineonly = len / 16; // print 16 bytes rather than 256
for (size_t i = 0; i < len; ++i) {
printf("%02x", buf[i]);
if (i % 16 == 15) {
printf("\n");
}
else {
printf(" ");
}
}
}
void update_count_data(uint8_t *cdata) {
uint8_t low = (uint8_t)counter; // get low byte of 16-bit var
uint8_t high = (uint8_t)(counter >> 8); // get high byte
printf("high %x low %x\n", high, low);
cdata[dataIxH] = high;
cdata[dataIxL] = low;
}
// handle aemlic status interrupts
void StatusIRQHandler(uint gpio, uint32_t events) {
gpio_set_irq_enabled(22, GPIO_IRQ_LEVEL_LOW, false); // disable irq
//printf("Status IRQ event %d %X\n", gpio, events);
//printf("gpio 22 0\n");
update_count_data(count_data);
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
flash_range_program(FLASH_TARGET_OFFSET, count_data, FLASH_PAGE_SIZE);
}
int main() {
stdio_init_all();
sleep_ms(SLEEP_MS_DEBOUNCE);
printf("\nStarting aemlic logger v 23 Sep 2022 05:40 ...\n");
gpio_init(25); // Pico built-in LED
gpio_set_dir(25, GPIO_OUT);
//printf("FLASH_PAGE_SIZE %u %d\n", FLASH_PAGE_SIZE, FLASH_PAGE_SIZE);
// 256 256 bytes
#if DO_DEBUG
printf("Previous count data:\n");
print_buf(flash_target_contents, FLASH_PAGE_SIZE);
#endif
// generate new count data or get existing data from flash
for (size_t i = 0; i < FLASH_PAGE_SIZE; ++i) {
//count_data[i] = 0x00; // only the first time the program runs
count_data[i] = flash_target_contents[i]; // subsequent times
}
// search for end of count_data; first pair of 0x00 values
int eod_found = false; // whether or not end-of-data was found
for (size_t i = 0; i < FLASH_PAGE_SIZE; i += 2) {
if ((count_data[i] == 0x00) && (count_data[i+1] == 0x00)) {
// found
dataIxH = i;
dataIxL = i + 1;
printf("found end of data. new dataIxH dataIxL %d %d\n",
dataIxH, dataIxL);
eod_found = true;
break;
}
}
if (!eod_found) {
printf("end of data not found (cd full). dataIxH dataIxL %d %d\n",
dataIxH, dataIxL);
// TODO re-init count_data to all zeroes, OR move to next buff ?
}
#if DO_DEBUG
printf("\nNew generated count data:\n");
print_buf(count_data, FLASH_PAGE_SIZE);
#endif
// Note that a whole number of sectors must be erased at a time.
//printf("\nErasing target region...\n");
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
#if DO_DEBUG
printf("Erased. Read back target region:\n");
print_buf(flash_target_contents, FLASH_PAGE_SIZE);
#endif
//printf("\nProgramming target region...\n");
flash_range_program(FLASH_TARGET_OFFSET, count_data, FLASH_PAGE_SIZE);
#if DO_DEBUG
printf("Programmed. Read back target region:\n");
print_buf(flash_target_contents, FLASH_PAGE_SIZE);
#endif
#if DO_DEBUG
bool mismatch = false;
for (int i = 0; i < FLASH_PAGE_SIZE; ++i) {
if (count_data[i] != flash_target_contents[i])
mismatch = true;
}
if (mismatch) {
printf("Programming failed!\n");
}
else {
printf("Programming successful!\n");
}
#endif
// aemlic STATUS
gpio_set_function(22, GPIO_FUNC_SIO); // software IO
gpio_set_dir(22, false); // input
gpio_pull_up(22);
// interrupt
gpio_set_irq_enabled_with_callback(22, GPIO_IRQ_LEVEL_LOW,
true, &StatusIRQHandler);
int looping = true;
while (looping) {
gpio_put(25, 1);
sleep_ms(SLEEP_MS_ON);
gpio_put(25, 0);
sleep_ms(SLEEP_MS_OFF);
// assume that counter is incremented every second
// print counter value every minute
counter++;
if (counter % 60 == 0) {
printf("counter: %d %x\n", counter, counter);
}
// aemlic STATUS
if (gpio_get(22)) { // 1
//printf("gpio 22 1\n");
}
else { // 0
printf("gpio 22 0 exit looping\n");
print_buf(flash_target_contents, FLASH_PAGE_SIZE);
looping = false;
}
}
printf("logger is exiting ...\n");
// there is no way to programmatically turn off Pico ?
// keep on-board LED permanently on while waiting for Pico to loose power
gpio_put(25, 1);
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment