feat: add lab-rv32i-c-gpio-edges-debounce card
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
#include "c13_common.h"
|
||||
|
||||
#define TASK04_GPIO_INPUT (UINT32_C(1) << 4)
|
||||
#define TASK04_GPIO_EFFECT (UINT32_C(1) << 0)
|
||||
#define TASK04_UART_EFFECT (UINT32_C(1) << 1)
|
||||
#define TASK04_TIMER_EFFECT (UINT32_C(1) << 2)
|
||||
#define TASK04_TIMER_PERIOD UINT64_C(10000)
|
||||
|
||||
volatile uint32_t g_task04_timer_irq_count;
|
||||
volatile uint32_t g_task04_timer_flag;
|
||||
volatile uint32_t g_task04_timer_mcause;
|
||||
volatile uint64_t g_task04_timer_deadline;
|
||||
volatile uint64_t g_task04_timer_observed;
|
||||
|
||||
volatile uint32_t g_task04_uart_irq_count;
|
||||
volatile uint32_t g_task04_uart_irq_number;
|
||||
volatile uint32_t g_task04_uart_byte;
|
||||
volatile uint32_t g_task04_uart_flag;
|
||||
|
||||
volatile uint32_t g_task04_gpio_irq_count;
|
||||
volatile uint32_t g_task04_gpio_irq_number;
|
||||
volatile uint32_t g_task04_gpio_level;
|
||||
volatile uint32_t g_task04_gpio_flag;
|
||||
|
||||
volatile uint32_t g_task04_main_timer_actions;
|
||||
volatile uint32_t g_task04_main_uart_actions;
|
||||
volatile uint32_t g_task04_main_gpio_actions;
|
||||
volatile uint32_t g_task04_final_out;
|
||||
volatile uint32_t g_task04_final_in;
|
||||
volatile uint32_t g_task04_pass;
|
||||
|
||||
void __attribute__((interrupt("machine"))) isr_machine_timer(void)
|
||||
{
|
||||
const uint64_t observed = c13_timer_read64();
|
||||
|
||||
g_task04_timer_mcause = read_csr(mcause);
|
||||
g_task04_timer_observed = observed;
|
||||
g_task04_timer_deadline += TASK04_TIMER_PERIOD;
|
||||
c13_timer_set_compare(g_task04_timer_deadline);
|
||||
g_task04_timer_flag = 1u;
|
||||
g_task04_timer_irq_count = g_task04_timer_irq_count + 1u;
|
||||
}
|
||||
|
||||
void task04_uart_handler(void)
|
||||
{
|
||||
g_task04_uart_irq_number = (uint32_t)h3irq_get_current_irq();
|
||||
g_task04_uart_byte = *tb_uart_reg(C13_UART_INDEX, TB_UART_DATA) & 0xffu;
|
||||
g_task04_uart_flag = 1u;
|
||||
g_task04_uart_irq_count = g_task04_uart_irq_count + 1u;
|
||||
}
|
||||
|
||||
void task04_gpio_handler(void)
|
||||
{
|
||||
const uint32_t pending = tb_gpio_read(TB_GPIO_PENDING);
|
||||
|
||||
g_task04_gpio_irq_number = (uint32_t)h3irq_get_current_irq();
|
||||
g_task04_gpio_level =
|
||||
(tb_gpio_read(TB_GPIO_IN) & TASK04_GPIO_INPUT) != 0u;
|
||||
tb_gpio_write(TB_GPIO_PENDING, pending);
|
||||
g_task04_gpio_flag = 1u;
|
||||
g_task04_gpio_irq_count = g_task04_gpio_irq_count + 1u;
|
||||
}
|
||||
|
||||
static uint32_t take_flag(volatile uint32_t *flag)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
global_irq_enable(false);
|
||||
value = *flag;
|
||||
*flag = 0u;
|
||||
global_irq_enable(true);
|
||||
return value;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const uint32_t output_mask =
|
||||
TASK04_GPIO_EFFECT | TASK04_UART_EFFECT | TASK04_TIMER_EFFECT;
|
||||
|
||||
global_irq_enable(false);
|
||||
timer_irq_enable(false);
|
||||
external_irq_enable(false);
|
||||
tb_uart_rx_irq_enable(C13_UART_INDEX, false);
|
||||
h3irq_enable(C13_UART_IRQ, false);
|
||||
h3irq_enable(C13_GPIO_IRQ, false);
|
||||
c13_timer_set_compare(UINT64_MAX);
|
||||
|
||||
tb_gpio_write(TB_GPIO_DIR, output_mask);
|
||||
tb_gpio_write(TB_GPIO_OUT_CLR, output_mask);
|
||||
tb_gpio_write(TB_GPIO_RISE_EN, 0u);
|
||||
tb_gpio_write(TB_GPIO_FALL_EN, 0u);
|
||||
tb_gpio_write(TB_GPIO_PENDING, UINT32_MAX);
|
||||
tb_gpio_test_set_input(0u);
|
||||
|
||||
h3irq_set_handler(C13_UART_IRQ, task04_uart_handler);
|
||||
h3irq_set_handler(C13_GPIO_IRQ, task04_gpio_handler);
|
||||
h3irq_set_priority(C13_UART_IRQ, 1u);
|
||||
h3irq_set_priority(C13_GPIO_IRQ, 2u);
|
||||
h3irq_enable(C13_UART_IRQ, true);
|
||||
h3irq_enable(C13_GPIO_IRQ, true);
|
||||
external_irq_enable(true);
|
||||
tb_uart_rx_irq_enable(C13_UART_INDEX, true);
|
||||
tb_gpio_write(TB_GPIO_RISE_EN, TASK04_GPIO_INPUT);
|
||||
|
||||
g_task04_timer_deadline = c13_timer_read64() + TASK04_TIMER_PERIOD;
|
||||
c13_timer_set_compare(g_task04_timer_deadline);
|
||||
timer_irq_enable(true);
|
||||
global_irq_enable(true);
|
||||
|
||||
/* Both writes are testbench stimuli, not production peripheral registers. */
|
||||
tb_uart_test_inject_rx(C13_UART_INDEX, (uint8_t)'U');
|
||||
tb_gpio_test_set_input(TASK04_GPIO_INPUT);
|
||||
|
||||
while (g_task04_main_timer_actions == 0u ||
|
||||
g_task04_main_uart_actions == 0u ||
|
||||
g_task04_main_gpio_actions == 0u) {
|
||||
if (take_flag(&g_task04_uart_flag) != 0u) {
|
||||
if (g_task04_uart_byte == (uint32_t)'U') {
|
||||
tb_gpio_write(TB_GPIO_OUT_SET, TASK04_UART_EFFECT);
|
||||
}
|
||||
g_task04_main_uart_actions++;
|
||||
}
|
||||
if (take_flag(&g_task04_gpio_flag) != 0u) {
|
||||
if (g_task04_gpio_level != 0u) {
|
||||
tb_gpio_write(TB_GPIO_OUT_SET, TASK04_GPIO_EFFECT);
|
||||
}
|
||||
g_task04_main_gpio_actions++;
|
||||
}
|
||||
if (take_flag(&g_task04_timer_flag) != 0u) {
|
||||
tb_gpio_write(TB_GPIO_OUT_SET, TASK04_TIMER_EFFECT);
|
||||
g_task04_main_timer_actions++;
|
||||
}
|
||||
if (g_task04_main_timer_actions == 0u ||
|
||||
g_task04_main_uart_actions == 0u ||
|
||||
g_task04_main_gpio_actions == 0u) {
|
||||
__asm__ volatile("wfi" ::: "memory");
|
||||
}
|
||||
}
|
||||
|
||||
global_irq_enable(false);
|
||||
timer_irq_enable(false);
|
||||
c13_timer_set_compare(UINT64_MAX);
|
||||
c13_external_disable();
|
||||
tb_gpio_write(TB_GPIO_RISE_EN, 0u);
|
||||
|
||||
g_task04_final_out = tb_gpio_read(TB_GPIO_OUT) & output_mask;
|
||||
g_task04_final_in = tb_gpio_read(TB_GPIO_IN) &
|
||||
(output_mask | TASK04_GPIO_INPUT);
|
||||
g_task04_pass =
|
||||
g_task04_timer_irq_count == 1u &&
|
||||
g_task04_timer_mcause == C13_MACHINE_TIMER_CAUSE &&
|
||||
g_task04_timer_observed >= g_task04_timer_deadline - TASK04_TIMER_PERIOD &&
|
||||
g_task04_uart_irq_count == 1u &&
|
||||
g_task04_uart_irq_number == C13_UART_IRQ &&
|
||||
g_task04_uart_byte == (uint32_t)'U' &&
|
||||
g_task04_gpio_irq_count == 1u &&
|
||||
g_task04_gpio_irq_number == C13_GPIO_IRQ &&
|
||||
g_task04_gpio_level == 1u &&
|
||||
g_task04_main_timer_actions == 1u &&
|
||||
g_task04_main_uart_actions == 1u &&
|
||||
g_task04_main_gpio_actions == 1u &&
|
||||
g_task04_final_out == output_mask &&
|
||||
g_task04_final_in == (output_mask | TASK04_GPIO_INPUT);
|
||||
|
||||
c13_report_u32("T04 timer_irq=", g_task04_timer_irq_count);
|
||||
c13_report_u32("T04 timer_mcause=", g_task04_timer_mcause);
|
||||
c13_report_u32("T04 uart_irq=", g_task04_uart_irq_count);
|
||||
c13_report_u32("T04 uart_number=", g_task04_uart_irq_number);
|
||||
c13_report_u32("T04 uart_byte=", g_task04_uart_byte);
|
||||
c13_report_u32("T04 gpio_irq=", g_task04_gpio_irq_count);
|
||||
c13_report_u32("T04 gpio_number=", g_task04_gpio_irq_number);
|
||||
c13_report_u32("T04 gpio_level=", g_task04_gpio_level);
|
||||
c13_report_u32("T04 main_timer=", g_task04_main_timer_actions);
|
||||
c13_report_u32("T04 main_uart=", g_task04_main_uart_actions);
|
||||
c13_report_u32("T04 main_gpio=", g_task04_main_gpio_actions);
|
||||
c13_report_u32("T04 final_out=", g_task04_final_out);
|
||||
c13_report_u32("T04 final_in=", g_task04_final_in);
|
||||
c13_report_u32("T04 pass=", g_task04_pass);
|
||||
return g_task04_pass ? 0 : 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user