Skip to content

Commit

Permalink
Enable HTTPS support and persistent memory to keep logs and RTC time …
Browse files Browse the repository at this point in the history
…after soft reset. (#9)
  • Loading branch information
tjko authored Jan 7, 2024
1 parent 59eaf24 commit 823753c
Show file tree
Hide file tree
Showing 13 changed files with 759 additions and 36 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ add_executable(brickpico
src/util.c
src/util_rp2040.c
src/log.c
src/crc32.c
src/ringbuffer.c
src/credits.s
)

Expand Down
64 changes: 64 additions & 0 deletions commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ BrickPico supports following commands:
* [SYStem:TIME?](#systemtime-1)
* [SYStem:TIMEZONE](#systemtimezone)
* [SYStem:TIMEZONE?](#systemtimezone-1)
* [SYStem:TLS:CERT](#systemtlscert)
* [SYStem:TLS:CERT?](#systemtlscert-1)
* [SYStem:TLS:PKEY](#systemtlspkey)
* [SYStem:TLS:PKEY?](#systemtlspkey-1)
* [SYStem:UPTIme?](#systemuptime)
* [SYStem:UPGRADE](#systemupgrade)
* [SYStem:VERsion?](#systemversion)
Expand Down Expand Up @@ -1274,6 +1278,66 @@ SYS:TIMEZONE?
PST8PDT7,M3.2.0/2,M11.1.0/02:00:00
```

#### SYStem:TLS:CERT
Upload or delete TLS certificate for the HTTP server.
Note, both certificate and private key must be installed before HTTPS server will
activate (when system is restarted next time).

When run withouth arguments this will prompt to paste TLS (X.509) certificate
in PEM format. When run with "DELETE" argument currently installed certificate
will be deleted.

Example (upload/paste certificate):
```
SYS:TLS:CERT
Paste certificate in PEM format:
```

Example (delete existing certificate from flash memory):
```
SYS:TLS:CERT DELETE
```

#### SYStem:TLS:CERT?
Display currently installed certificate.

Example:
```
SYS:TLS:CERT?
```


#### SYStem:TLS:PKEY
Upload or delete (TLS Certificate) Private key for the HTTP server.
Note, both certificate and private key must be installed before HTTPS server will
activate (when system is restarted next time).

When run withouth arguments this will prompt to paste private key
in PEM format. When run with "DELETE" argument currently installed private key
will be deleted.

Example (upload/paste private key):
```
SYS:TLS:PKEY
Paste private key in PEM format:
```

Example (delete existing private key from flash memory):
```
SYS:TLS:PKEY DELETE
```

#### SYStem:TLS:PKEY?
Display currently installed private key.

Example:
```
SYS:TLS:CERT?
```


#### SYStem:UPTIme?
Return time elapsed since unit was last rebooted.

Expand Down
86 changes: 83 additions & 3 deletions src/brickpico.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "hardware/watchdog.h"
#include "hardware/vreg.h"

#include "ringbuffer.h"
#include "brickpico.h"


Expand All @@ -48,11 +49,72 @@ static struct brickpico_state transfer_state;
static struct brickpico_state system_state;
struct brickpico_state *brickpico_state = &system_state;

struct persistent_memory_block __uninitialized_ram(persistent_memory);
struct persistent_memory_block *persistent_mem = &persistent_memory;
ringbuffer_t *log_rb = NULL;

#define PERSISTENT_MEMORY_ID 0xbaddecaf
#define PERSISTENT_MEMORY_CRC_LEN offsetof(struct persistent_memory_block, crc32)

auto_init_mutex(pmem_mutex_inst);
mutex_t *pmem_mutex = &pmem_mutex_inst;
auto_init_mutex(state_mutex_inst);
mutex_t *state_mutex = &state_mutex_inst;
bool rebooted_by_watchdog = false;


void update_persistent_memory_crc()
{
struct persistent_memory_block *m = persistent_mem;

m->crc32 = xcrc32((unsigned char*)m, PERSISTENT_MEMORY_CRC_LEN, 0);
}

void init_persistent_memory()
{
struct persistent_memory_block *m = persistent_mem;
uint32_t crc;
char s[32];

if (m->id == PERSISTENT_MEMORY_ID) {
crc = xcrc32((unsigned char*)m, PERSISTENT_MEMORY_CRC_LEN, 0);
if (crc == m->crc32) {
printf("Found persistent memory block\n");
datetime_str(s, sizeof(s), &m->saved_time);
if (!rtc_set_datetime(&m->saved_time)) {
printf("Failed to restore RTC clock: %s\n", s);
}
if (m->uptime) {
m->prev_uptime = m->uptime;
update_persistent_memory_crc();
}
return;
}
printf("Found corrupt persistent memory block"
" (CRC-32 mismatch %08lx != %08lx)\n", crc, m->crc32);
}

printf("Initializing persistent memory block...\n");
memset(m, 0, sizeof(*m));
m->id = PERSISTENT_MEMORY_ID;
ringbuffer_init(&m->log_rb, m->log, sizeof(m->log));
update_persistent_memory_crc();
}

void update_persistent_memory()
{
struct persistent_memory_block *m = persistent_mem;
datetime_t t;

mutex_enter_blocking(pmem_mutex);
if (rtc_get_datetime(&t)) {
m->saved_time = t;
}
m->uptime = to_us_since_boot(get_absolute_time());
update_persistent_memory_crc();
mutex_exit(pmem_mutex);
}

void boot_reason()
{
printf(" CHIP_RESET: %08lx\n", vreg_and_chip_reset_hw->chip_reset);
Expand All @@ -61,6 +123,7 @@ void boot_reason()

void setup()
{
datetime_t t;
int i = 0;

rtc_init();
Expand All @@ -79,6 +142,7 @@ void setup()
#if TTL_SERIAL > 0
stdio_uart_init_full(TTL_SERIAL_UART,
TTL_SERIAL_SPEED, TX_PIN, RX_PIN);
sleep_ms(5);
#endif
printf("\n\n");
#ifndef NDEBUG
Expand All @@ -99,6 +163,20 @@ void setup()
clock_get_hz(clk_sys) / 1000000.0);
printf(" Serial Number: %s\n\n", pico_serial_str());

init_persistent_memory();
log_rb = &persistent_mem->log_rb;
printf("\n");

log_msg(LOG_NOTICE, "System starting...");
if (persistent_mem->prev_uptime) {
log_msg(LOG_NOTICE, "Uptime before soft reset: %llus\n",
persistent_mem->prev_uptime / 1000000);
}
if (rtc_get_datetime(&t)) {
char buf[32];
log_msg(LOG_NOTICE, "RTC clock time: %s", datetime_str(buf, sizeof(buf), &t));
}

display_init();
network_init(&system_state);

Expand Down Expand Up @@ -236,7 +314,7 @@ int main()
{
absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(t_led, 0);
absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(t_network, 0);
absolute_time_t t_now, t_last, t_display, t_timer, t_temp;
absolute_time_t t_now, t_last, t_display, t_timer, t_temp, t_ram;
uint8_t led_state = 0;
int64_t max_delta = 0;
int64_t delta;
Expand Down Expand Up @@ -268,7 +346,7 @@ int main()
#endif

t_last = get_absolute_time();
t_temp = t_timer = t_display = t_last;
t_ram = t_temp = t_timer = t_display = t_last;

while (1) {
t_now = get_absolute_time();
Expand All @@ -283,6 +361,9 @@ int main()
if (time_passed(&t_network, 100)) {
network_poll();
}
if (time_passed(&t_ram, 1000)) {
update_persistent_memory();
}

/* Toggle LED every 1000ms */
if (time_passed(&t_led, 1000)) {
Expand All @@ -306,7 +387,6 @@ int main()

/* Update display every 1000ms */
if (time_passed(&t_display, 1000)) {
log_msg(LOG_DEBUG, "Update display");
update_core1_state();
display_status(brickpico_state, cfg);
}
Expand Down
22 changes: 22 additions & 0 deletions src/brickpico.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "lwip/ip_addr.h"
#endif

#include "ringbuffer.h"

#ifndef BRICKPICO_MODEL
#error unknown board model
#endif
Expand Down Expand Up @@ -145,10 +147,27 @@ struct brickpico_state {
};


struct persistent_memory_block {
uint32_t id;
datetime_t saved_time;
uint64_t uptime;
uint64_t prev_uptime;
ringbuffer_t log_rb;
uint32_t crc32;
uint8_t log[8192];
};



/* brickpico.c */
extern ringbuffer_t *log_rb;
extern struct persistent_memory_block *persistent_mem;
extern struct brickpico_state *brickpico_state;
extern bool rebooted_by_watchdog;
extern mutex_t *pmem_mutex;
extern mutex_t *state_mutex;
void update_persistent_memory_crc();
void update_persistent_memory();
void update_display_state();
void update_core1_state();

Expand Down Expand Up @@ -284,5 +303,8 @@ int getstring_timeout_ms(char *str, uint32_t maxlen, uint32_t timeout);
double get_temperature(double adc_ref_voltage, double temp_offset, double temp_coefficient);
void update_temp(const struct brickpico_config *conf, struct brickpico_state *state);

/* crc32.c */
unsigned int xcrc32 (const unsigned char *buf, int len, unsigned int init);


#endif /* BRICKPICO_H */
Loading

0 comments on commit 823753c

Please sign in to comment.