Skip to content

Commit c3798ee

Browse files
committed
Add sem_drain_and_wait_timeout and time_to_ticks to lispBM.
The new `sem_drain_and_wait_timeout` effectively achieves binary semaphore semantics without relying on `ch_binary_semaphore`. `time_to_ticks` is necessary to pass the correct timeout values to `sem_wait_to` and `sem_drain_and_wait_timeout`
1 parent 68094e9 commit c3798ee

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

lispBM/c_libs/vesc_c_if.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,12 +650,16 @@ typedef struct {
650650
const float* (*foc_get_audio_sample_table)(int channel);
651651
bool (*foc_play_audio_samples)(const int8_t *samples, int num_samp, float f_samp, float voltage);
652652

653-
// Semaphore
653+
// Semaphores
654654
lib_semaphore (*sem_create)(void); // Use VESC_IF->free on the semaphore when done with it
655655
void (*sem_wait)(lib_semaphore);
656656
void (*sem_signal)(lib_semaphore);
657657
bool (*sem_wait_to)(lib_semaphore, systime_t); // Returns false on timeout
658658
void (*sem_reset)(lib_semaphore);
659+
int32_t (*sem_drain_and_wait_timeout)(lib_semaphore, systime_t);
660+
661+
// Os continued
662+
systime_t (*time_to_ticks)(uint32_t seconds, uint32_t millis, uint32_t micros);
659663
} vesc_c_if;
660664

661665
typedef struct {

lispBM/lispif_c_lib.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,33 @@ static void lib_sem_reset(lib_semaphore s) {
655655
chSemReset((semaphore_t*)s, 0);
656656
}
657657

658+
// Guaranteed to block. First drains the semaphore to 0 if its counter is positive and
659+
// then waits on it with given timeout(special values TIME_IMMEDIATE and TIME_INFINITE are honored).
660+
// Returns MSG_RESET or MSG_TIMEOUT if that was the result of the wait operations.
661+
// Otherwise returns a non-negative number of overruns, i.e. the number by which the semaphore
662+
// had to be decreased before the wait operation.
663+
//
664+
// Useful for implementing binary-semaphore like semantics where it's important to ignore
665+
// semaphore overruns.
666+
static int32_t lib_sem_drain_and_wait_timeout(lib_semaphore sem, systime_t timeout) {
667+
chSysLock();
668+
const cnt_t sem_counter = chSemGetCounterI((semaphore_t*)sem);
669+
// setCounter isn't exposed and I don't want to manually manipulate the internal counter
670+
for (cnt_t i = 0; i < sem_counter; i++) {
671+
chSemFastWaitI((semaphore_t*)sem);
672+
}
673+
const msg_t wait_result = chSemWaitTimeoutS((semaphore_t*)sem, timeout);
674+
chSysUnlock();
675+
if (wait_result < 0) { // MSG_RESET and MSG_TIMEOUT are negative
676+
return wait_result;
677+
}
678+
return sem_counter < 0 ? 0 : sem_counter;
679+
}
680+
681+
static systime_t lib_time_to_ticks(uint32_t seconds, uint32_t millis, uint32_t micros) {
682+
return S2ST(seconds) + MS2ST(millis) + US2ST(micros);
683+
}
684+
658685
static remote_state lib_get_remote_state(void) {
659686
remote_state res;
660687
res.js_x = app_nunchuk_get_decoded_x();
@@ -1022,6 +1049,10 @@ lbm_value ext_load_native_lib(lbm_value *args, lbm_uint argn) {
10221049
cif.cif.sem_signal = lib_sem_signal;
10231050
cif.cif.sem_wait_to = lib_sem_wait_to;
10241051
cif.cif.sem_reset = lib_sem_reset;
1052+
cif.cif.sem_drain_and_wait_timeout = lib_sem_drain_and_wait_timeout;
1053+
1054+
// OS continued
1055+
cif.cif.time_to_ticks = lib_time_to_ticks;
10251056

10261057
lib_init_done = true;
10271058
}

0 commit comments

Comments
 (0)