Verified Commit 32808693 authored by Rahix's avatar Rahix
Browse files

fix(serial): Fix UART receive call violating API rules


Signed-off-by: Rahix's avatarRahix <rahix@rahix.de>
parent 7d854dee
...@@ -29,8 +29,9 @@ typedef unsigned int size_t; ...@@ -29,8 +29,9 @@ typedef unsigned int size_t;
/* clang-format off */ /* clang-format off */
#define API_SYSTEM_EXIT 0x1 /* TODO */ #define API_SYSTEM_EXIT 0x1 /* TODO */
#define API_SYSTEM_EXEC 0x2 /* TODO */ #define API_SYSTEM_EXEC 0x2 /* TODO */
#define API_UART_WRITE 0x3 #define API_UART_WRITE_STR 0x3
#define API_UART_READ 0x4 #define API_UART_READ_CHAR 0x4
#define API_UART_READ_STR 0x5 /* TODO */
#define API_STREAM_READ 0x6 #define API_STREAM_READ 0x6
#define API_INTERRUPT_ENABLE 0x7 #define API_INTERRUPT_ENABLE 0x7
#define API_INTERRUPT_DISABLE 0x8 #define API_INTERRUPT_DISABLE 0x8
...@@ -102,7 +103,7 @@ API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id)); ...@@ -102,7 +103,7 @@ API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id));
#define EPIC_INT_RESET 0 #define EPIC_INT_RESET 0
/** ``^C`` interrupt. See :c:func:`epic_isr_ctrl_c` for details. */ /** ``^C`` interrupt. See :c:func:`epic_isr_ctrl_c` for details. */
#define EPIC_INT_CTRL_C 1 #define EPIC_INT_CTRL_C 1
/** TODO */ /** UART Receive interrupt. See :c:func:`epic_isr_uart_rx`. */
#define EPIC_INT_UART_RX 2 #define EPIC_INT_UART_RX 2
/** RTC Alarm interrupt. See :c:func:`epic_isr_rtc_alarm` */ /** RTC Alarm interrupt. See :c:func:`epic_isr_rtc_alarm` */
#define EPIC_INT_RTC_ALARM 3 #define EPIC_INT_RTC_ALARM 3
...@@ -129,19 +130,49 @@ API_ISR(EPIC_INT_RESET, epic_isr_reset); ...@@ -129,19 +130,49 @@ API_ISR(EPIC_INT_RESET, epic_isr_reset);
* :param str: String to write. Does not necessarily have to be NULL-terminated. * :param str: String to write. Does not necessarily have to be NULL-terminated.
* :param length: Amount of bytes to print. * :param length: Amount of bytes to print.
*/ */
API(API_UART_WRITE, void epic_uart_write_str(const char *str, intptr_t length)); API(API_UART_WRITE_STR, void epic_uart_write_str(
const char *str,
intptr_t length
));
/** /**
* Blocking read a single character from any connected serial device.
* ``epic_uart_read_chr`` only returns once one byte has been read.
* *
* .. todo:: * Try reading a single character from any connected serial device. If nothing
* is available, :c:func:`epic_uart_read_char` returns ``(-1)``.
* *
* This API function is currently in violation of the API rules. * :return: The byte or ``(-1)`` if no byte was available.
*/
API(API_UART_READ_CHAR, int epic_uart_read_char(void));
/**
* **Interrupt Service Routine**
*
* UART receive interrupt. This interrupt is triggered whenever a new character
* becomes available on any connected UART device. This function is weakly
* aliased to :c:func:`epic_isr_default` by default.
*
* **Example**:
* *
* :return: The byte. * .. code-block:: cpp
*
* void epic_isr_uart_rx(void)
* {
* char buffer[33];
* int n = epic_uart_read_str(&buffer, sizeof(buffer) - 1);
* buffer[n] = '\0';
* printf("Got: %s\n", buffer);
* }
*
* int main(void)
* {
* epic_interrupt_enable(EPIC_INT_UART_RX);
*
* while (1) {
* __WFI();
* }
* }
*/ */
API(API_UART_READ, char epic_uart_read_chr(void)); API_ISR(EPIC_INT_UART_RX, epic_isr_uart_rx);
/** /**
* **Interrupt Service Routine** * **Interrupt Service Routine**
......
#include <stdint.h> #include "epicardium.h"
#include <stdio.h> #include "api/interrupt-sender.h"
#include "modules/log.h"
#include "modules/modules.h"
#include "max32665.h" #include "max32665.h"
#include "cdcacm.h" #include "cdcacm.h"
...@@ -9,9 +11,8 @@ ...@@ -9,9 +11,8 @@
#include "task.h" #include "task.h"
#include "queue.h" #include "queue.h"
#include "modules.h" #include <stdint.h>
#include "modules/log.h" #include <stdio.h>
#include "api/interrupt-sender.h"
/* Task ID for the serial handler */ /* Task ID for the serial handler */
TaskHandle_t serial_task_id = NULL; TaskHandle_t serial_task_id = NULL;
...@@ -31,13 +32,15 @@ void epic_uart_write_str(const char *str, intptr_t length) ...@@ -31,13 +32,15 @@ void epic_uart_write_str(const char *str, intptr_t length)
} }
/* /*
* Blocking API-call to read a character from the queue. * API-call to read a character from the queue.
*/ */
char epic_uart_read_chr(void) int epic_uart_read_char(void)
{ {
char chr; char chr;
xQueueReceive(read_queue, &chr, portMAX_DELAY); if (xQueueReceive(read_queue, &chr, 0) == pdTRUE) {
return chr; return (int)chr;
}
return (-1);
} }
/* Interrupt handler needed for SDK UART implementation */ /* Interrupt handler needed for SDK UART implementation */
...@@ -64,6 +67,8 @@ static void enqueue_char(char chr) ...@@ -64,6 +67,8 @@ static void enqueue_char(char chr)
/* Queue overran, wait a bit */ /* Queue overran, wait a bit */
vTaskDelay(portTICK_PERIOD_MS * 50); vTaskDelay(portTICK_PERIOD_MS * 50);
} }
api_interrupt_trigger(EPIC_INT_UART_RX);
} }
void vSerialTask(void *pvParameters) void vSerialTask(void *pvParameters)
......
#include "mphalport.h"
#include "max32665.h" #include "max32665.h"
#include "lib/utils/pyexec.h" #include "lib/utils/pyexec.h"
...@@ -13,12 +15,11 @@ extern void *__HeapBase, *__HeapLimit; ...@@ -13,12 +15,11 @@ extern void *__HeapBase, *__HeapLimit;
int main(void) int main(void)
{ {
pycardium_hal_init();
mp_stack_set_top(&__StackTop); mp_stack_set_top(&__StackTop);
mp_stack_set_limit((mp_int_t)&__StackLimit); mp_stack_set_limit((mp_int_t)&__StackLimit);
/* TMR5 is used to notify on keyboard interrupt */
NVIC_EnableIRQ(TMR5_IRQn);
while (1) { while (1) {
gc_init(&__HeapBase + 1024 * 10, &__HeapLimit); gc_init(&__HeapBase + 1024 * 10, &__HeapLimit);
......
#include "api/common.h"
#include "epicardium.h" #include "epicardium.h"
#include "api/common.h"
#include "max32665.h" #include "max32665.h"
#include "mxc_delay.h" #include "mxc_delay.h"
...@@ -20,6 +20,19 @@ ...@@ -20,6 +20,19 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
/* Initialize everything for MicroPython */
void pycardium_hal_init(void)
{
/* TMR5 is used for interrupts from Epicardium */
NVIC_EnableIRQ(TMR5_IRQn);
/*
* Enable UART RX Interrupt so Pycardium can sleep until
* a character becomes available.
*/
epic_interrupt_enable(EPIC_INT_UART_RX);
}
/****************************************************************************** /******************************************************************************
* Serial Communication * Serial Communication
*/ */
...@@ -27,7 +40,11 @@ ...@@ -27,7 +40,11 @@
/* Receive single character */ /* Receive single character */
int mp_hal_stdin_rx_chr(void) int mp_hal_stdin_rx_chr(void)
{ {
return (int)epic_uart_read_chr(); int chr;
while ((chr = epic_uart_read_char()) < 0) {
__WFI();
}
return chr;
} }
/* Send a string */ /* Send a string */
......
#include "py/mpconfig.h" #include "py/mpconfig.h"
void mp_hal_set_interrupt_char(char c); void mp_hal_set_interrupt_char(char c);
/* Init everything */
void pycardium_hal_init(void);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment