[sw/sca] Refactor common sca code in preparation for a new library
This change refactors some device init and handling code that is
expected to be shared between different SCA targets:
- Initialization of pinmux, UART, GPIO, and timer,
- IRQ handling,
- Trigger handling, and
- Sleeping during encryption operations.
Signed-off-by: Alphan Ulusoy <alphan@google.com>
diff --git a/sw/device/sca/aes_serial/aes_serial.c b/sw/device/sca/aes_serial/aes_serial.c
index c9d0366..26f2077 100644
--- a/sw/device/sca/aes_serial/aes_serial.c
+++ b/sw/device/sca/aes_serial/aes_serial.c
@@ -90,6 +90,116 @@
} while (false)
/**
+ * Initializes the UART peripheral.
+ */
+static void sca_init_uart() {
+ (void)dif_uart_init(
+ (dif_uart_params_t){
+ .base_addr = mmio_region_from_addr(TOP_EARLGREY_UART_BASE_ADDR),
+ },
+ &uart);
+ (void)dif_uart_configure(&uart, (dif_uart_config_t){
+ .baudrate = kUartBaudrate,
+ .clk_freq_hz = kClockFreqPeripheralHz,
+ .parity_enable = kDifUartToggleDisabled,
+ .parity = kDifUartParityEven,
+ });
+ dif_uart_fifo_reset(&uart, kDifUartFifoResetAll);
+ base_uart_stdout(&uart);
+}
+
+/**
+ * Initializes the GPIO peripheral.
+ */
+static void sca_init_gpio() {
+ dif_gpio_params_t gpio_params = {
+ .base_addr = mmio_region_from_addr(TOP_EARLGREY_GPIO_BASE_ADDR)};
+ (void)dif_gpio_init(gpio_params, &gpio);
+ (void)dif_gpio_output_set_enabled_all(&gpio, kGpioCaptureTriggerHigh);
+}
+
+/**
+ * Initializes the timer peripheral.
+ */
+static void sca_init_timer() {
+ (void)dif_rv_timer_init(
+ mmio_region_from_addr(TOP_EARLGREY_RV_TIMER_BASE_ADDR),
+ (dif_rv_timer_config_t){.hart_count = 1, .comparator_count = 1}, &timer);
+ dif_rv_timer_tick_params_t tick_params;
+ (void)dif_rv_timer_approximate_tick_params(kClockFreqPeripheralHz,
+ kClockFreqCpuHz, &tick_params);
+ (void)dif_rv_timer_set_tick_params(&timer, kRvTimerHart, tick_params);
+ (void)dif_rv_timer_irq_enable(&timer, kRvTimerHart, kRvTimerComparator,
+ kDifRvTimerEnabled);
+ irq_timer_ctrl(true);
+ irq_global_ctrl(true);
+}
+
+/**
+ * Timer IRQ handler.
+ *
+ * Disables the counter and clears pending interrupts.
+ */
+void handler_irq_timer(void) {
+ // Return values of below functions are ignored to improve capture
+ // performance.
+ (void)dif_rv_timer_counter_set_enabled(&timer, kRvTimerHart,
+ kDifRvTimerDisabled);
+ (void)dif_rv_timer_irq_clear(&timer, kRvTimerHart, kRvTimerComparator);
+}
+
+/**
+ * Initializes the peripherals (pinmux, uart, gpio, and timer) used by SCA code.
+ */
+static void sca_init(void) {
+ pinmux_init();
+ sca_init_uart();
+ sca_init_gpio();
+ sca_init_timer();
+}
+
+/**
+ * Sets capture trigger high.
+ *
+ * The actual trigger signal used for capture is a combination (logical AND) of:
+ * - GPIO15 enabled here, and
+ * - the busy signal of the AES unit. This signal will go high 40 cycles
+ * after aes_manual_trigger() is executed below and remain high until
+ * the operation has finished.
+ */
+static void sca_set_trigger_high() {
+ (void)dif_gpio_write_all(&gpio, kGpioCaptureTriggerHigh);
+}
+
+/**
+ * Sets capture trigger low.
+ */
+static void sca_set_trigger_low() {
+ (void)dif_gpio_write_all(&gpio, kGpioCaptureTriggerLow);
+}
+
+/**
+ * Functions called by `sca_call_and_sleep()` must conform to this prototype.
+ */
+typedef void (*sca_callee)(void);
+
+static void sca_call_and_sleep(sca_callee callee, uint32_t sleep_cycles) {
+ // Start timer to wake Ibex after AES is done.
+ uint64_t current_time;
+ // Return values of below functions are ignored to improve capture
+ // performance.
+ (void)dif_rv_timer_counter_read(&timer, kRvTimerHart, ¤t_time);
+ (void)dif_rv_timer_arm(&timer, kRvTimerHart, kRvTimerComparator,
+ current_time + sleep_cycles);
+ (void)dif_rv_timer_counter_set_enabled(&timer, kRvTimerHart,
+ kDifRvTimerEnabled);
+
+ callee();
+
+ wait_for_interrupt();
+}
+
+/**
* Convert `from` binary `to` hex.
*
* @param from input value in binary format.
@@ -201,33 +311,15 @@
// Provide input data to AES.
aes_data_put_wait(plaintext);
- // Arm capture trigger. The actual trigger signal used for capture is a
- // combination (logical AND) of:
- // - GPIO15 enabled here, and
- // - the busy signal of the AES unit. This signal will go high 40 cycles
- // after aes_manual_trigger() is executed below and remain high until
- // the operation has finished.
- SS_CHECK(dif_gpio_write_all(&gpio, kGpioCaptureTriggerHigh) == kDifGpioOk);
-
- // Start timer to wake up Ibex after AES is done.
- uint64_t current_time;
- SS_CHECK(dif_rv_timer_counter_read(&timer, kRvTimerHart, ¤t_time) ==
- kDifRvTimerOk);
- SS_CHECK(dif_rv_timer_arm(&timer, kRvTimerHart, kRvTimerComparator,
- current_time + kIbexAesSleepCycles) ==
- kDifRvTimerOk);
- SS_CHECK(dif_rv_timer_counter_set_enabled(
- &timer, kRvTimerHart, kDifRvTimerEnabled) == kDifRvTimerOk);
+ sca_set_trigger_high();
// Start AES operation (this triggers the capture) and go to sleep.
// Using the SecAesStartTriggerDelay hardware parameter, the AES unit is
// configured to start operation 40 cycles after receiving the start trigger.
// This allows Ibex to go to sleep in order to not disturb the capture.
- aes_manual_trigger();
- wait_for_interrupt();
+ sca_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles);
- // Disable capture trigger.
- SS_CHECK(dif_gpio_write_all(&gpio, kGpioCaptureTriggerLow) == kDifGpioOk);
+ sca_set_trigger_low();
// Retrieve output data from AES.
aes_data_get_wait(ciphertext);
@@ -282,42 +374,7 @@
}
int main(void) {
- CHECK(dif_uart_init(
- (dif_uart_params_t){
- .base_addr = mmio_region_from_addr(TOP_EARLGREY_UART_BASE_ADDR),
- },
- &uart) == kDifUartOk);
- CHECK(dif_uart_configure(&uart, (dif_uart_config_t){
- .baudrate = kUartBaudrate,
- .clk_freq_hz = kClockFreqPeripheralHz,
- .parity_enable = kDifUartToggleDisabled,
- .parity = kDifUartParityEven,
- }) == kDifUartConfigOk);
- base_uart_stdout(&uart);
-
- pinmux_init();
-
- irq_global_ctrl(true);
- irq_timer_ctrl(true);
-
- CHECK(dif_rv_timer_init(
- mmio_region_from_addr(TOP_EARLGREY_RV_TIMER_BASE_ADDR),
- (dif_rv_timer_config_t){.hart_count = 1, .comparator_count = 1},
- &timer) == kDifRvTimerOk);
- dif_rv_timer_tick_params_t tick_params;
- CHECK(dif_rv_timer_approximate_tick_params(kClockFreqPeripheralHz,
- kClockFreqCpuHz, &tick_params) ==
- kDifRvTimerApproximateTickParamsOk);
- CHECK(dif_rv_timer_set_tick_params(&timer, kRvTimerHart, tick_params) ==
- kDifRvTimerOk);
- CHECK(dif_rv_timer_irq_enable(&timer, kRvTimerHart, kRvTimerComparator,
- kDifRvTimerEnabled) == kDifRvTimerOk);
-
- dif_gpio_params_t gpio_params = {
- .base_addr = mmio_region_from_addr(TOP_EARLGREY_GPIO_BASE_ADDR)};
- CHECK(dif_gpio_init(gpio_params, &gpio) == kDifGpioOk);
- CHECK(dif_gpio_output_set_enabled_all(&gpio, 0x08200) == kDifGpioOk);
- CHECK(dif_gpio_write_all(&gpio, kGpioCaptureTriggerLow) == kDifGpioOk);
+ sca_init();
aes_cfg_t aes_cfg;
aes_cfg.key_len = kAes128;
@@ -351,15 +408,3 @@
}
}
}
-
-void handler_irq_timer(void) {
- bool irq_flag;
- CHECK(dif_rv_timer_irq_get(&timer, kRvTimerHart, kRvTimerComparator,
- &irq_flag) == kDifRvTimerOk);
- CHECK(irq_flag, "Entered IRQ handler but the expected IRQ flag wasn't set!");
-
- CHECK(dif_rv_timer_counter_set_enabled(&timer, kRvTimerHart,
- kDifRvTimerDisabled) == kDifRvTimerOk);
- CHECK(dif_rv_timer_irq_clear(&timer, kRvTimerHart, kRvTimerComparator) ==
- kDifRvTimerOk);
-}