Created
September 23, 2022 11:20
-
-
Save kenwebb/85a98420fb0b0dc8f02a48fafc8c49d7 to your computer and use it in GitHub Desktop.
Log activity of the aemlic v2 board
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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