diff options
author | Sergey Nazaryev <sergey@nazaryev.ru> | 2018-10-11 19:09:20 +0000 |
---|---|---|
committer | Sergey Nazaryev <sergey@nazaryev.ru> | 2018-10-11 19:11:44 +0000 |
commit | dd58e3e400aa5503f6356a8384584dfd7d428b7f (patch) | |
tree | 23c9abe0b51e532eb04453839de1be7e6c76dcb9 | |
parent | 8799ba4337025b1d74c0876179ee8e9519e349f3 (diff) | |
download | zybo-z7-baremetal-dd58e3e400aa5503f6356a8384584dfd7d428b7f.zip zybo-z7-baremetal-dd58e3e400aa5503f6356a8384584dfd7d428b7f.tar.gz zybo-z7-baremetal-dd58e3e400aa5503f6356a8384584dfd7d428b7f.tar.bz2 |
Porting application to Cortex-A9 from
https://raw.githubusercontent.com/libopencm3/libopencm3-examples/d90d72291a1314b121cc06147941a258154a9697/examples/stm32/f4/nucleo-f411re/usart-stdio/usart-stdio.c
-rw-r--r-- | examples/uart/uart.c | 312 |
1 files changed, 239 insertions, 73 deletions
diff --git a/examples/uart/uart.c b/examples/uart/uart.c index ac7f50d..acf38c7 100644 --- a/examples/uart/uart.c +++ b/examples/uart/uart.c @@ -1,11 +1,9 @@ #include <stdint.h> - -#define MIO_PIN07_CTRL *((uint32_t *)0xF800071C) -#define MIO_PIN07_CTRL_GPIO0 0x00003200 -#define GPIO_DIRM0 *((uint32_t *)0xE000A204) -#define GPIO_OEN0 *((uint32_t *)0xE000A208) -#define GPIO_DATA0 *((uint32_t *)0xE000A040) -#define GPIO0_PIN7 0x80 +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> +#include <unistd.h> #define XUARTPS_CR_TXRST 0x00000002U /**< TX logic reset */ #define XUARTPS_CR_RXRST 0x00000001U /**< RX logic reset */ @@ -33,82 +31,250 @@ #define XUARTPS_CR_RX_DIS 0x00000008U /**< RX disabled. */ #define XUARTPS_CR_RX_EN 0x00000004U /**< RX enabled */ -#define POuint32_tER_TO_REGISTER(REG) ( *((volatile uint32_t*)(REG))) //u32 (xil_types.h) data type is declared as uuint32_t32_t (stduint32_t.h) +#define POINTER_TO_REGISTER(REG) ( *((volatile uint32_t*)(REG))) + +#define UART_BASE XPS_UART1_BASEADDR +#define UART_CTRL POINTER_TO_REGISTER(UART_BASE + XUARTPS_CR_OFFSET) // Control Register +#define UART_MODE POINTER_TO_REGISTER(UART_BASE + XUARTPS_MR_OFFSET) // Mode Register + +#define UART_BAUD_GEN POINTER_TO_REGISTER(UART_BASE + XUARTPS_BAUDGEN_OFFSET) // Baud Rate Generator "CD" +#define UART_BAUD_DIV POINTER_TO_REGISTER(UART_BASE + XUARTPS_BAUDDIV_OFFSET) // Baud Rate Divider "BDIV" +#define UART_FIFO POINTER_TO_REGISTER(UART_BASE + XUARTPS_FIFO_OFFSET) // FIFO +#define UART_STATUS POINTER_TO_REGISTER(UART_BASE + XUARTPS_SR_OFFSET) // Channel Status + +#define MIO_PIN07_CTRL *((uint32_t *)0xF800071C) +#define MIO_PIN07_CTRL_GPIO0 0x00003200 + +#define GPIO_DIRM0 *((uint32_t *)0xE000A204) +#define GPIO_OEN0 *((uint32_t *)0xE000A208) +#define GPIO_DATA0 *((uint32_t *)0xE000A040) -#define UART_BASE XPS_UART1_BASEADDR // Base Address -#define UART_CTRL POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_CR_OFFSET) // Control Register -#define UART_MODE POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_MR_OFFSET) // Mode Register +#define GPIO0_PIN7 0x80 -#define UART_BAUD_GEN POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_BAUDGEN_OFFSET) // Baud Rate Generator "CD" -#define UART_BAUD_DIV POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_BAUDDIV_OFFSET) // Baud Rate Divider "BDIV" -#define UART_FIFO POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_FIFO_OFFSET) // FIFO -#define UART_STATUS POuint32_tER_TO_REGISTER(UART_BASE + XUARTPS_SR_OFFSET) // Channel Status +/* + * To implement the STDIO functions you need to create + * the _read and _write functions and hook them to the + * USART you are using. This example also has a buffered + * read function for basic line editing. + */ +int _write(int fd, char *ptr, int len); +int _read(int fd, char *ptr, int len); +void get_buffered_line(void); -#define BUFFER_SIZE 20 +/* + * This is a pretty classic ring buffer for characters + */ +#define BUFLEN 127 -static char str[] = "\tHello World\r"; +static uint16_t start_ndx; +static uint16_t end_ndx; +static char buf[BUFLEN+1]; +#define buf_len ((end_ndx - start_ndx) % BUFLEN) +static inline int inc_ndx(int n) { return ((n + 1) % BUFLEN); } +static inline int dec_ndx(int n) { return (((n + BUFLEN) - 1) % BUFLEN); } -// Send one character through UART interface void uart_send(char c) { - while (UART_STATUS & XUARTPS_SR_TNFUL); - UART_FIFO = c; - while (UART_STATUS & XUARTPS_SR_TACTIVE); + while (UART_STATUS & XUARTPS_SR_TNFUL); + UART_FIFO = c; + while (UART_STATUS & XUARTPS_SR_TACTIVE); } -// Send string (character array) through UART interface -void uart_send_string(char str[BUFFER_SIZE]) { - char *ptr = str; +char uart_recv() { + if ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY) + return 0; - while (*ptr != '\0') { - uart_send(*ptr); - ptr++; - } - } + return UART_FIFO; +} -// Check if UART receive FIFO is not empty and return the new data -char uart_receive() { - if ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY) return 0; - return UART_FIFO; +char uart_recv_blocking() { + while ((UART_STATUS & XUARTPS_SR_RXEMPTY) == XUARTPS_SR_RXEMPTY); + return UART_FIFO; } -int main(void) { - uint32_t r = 0; // Temporary value variable - - r = UART_CTRL; - r &= ~(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN); // Clear Tx & Rx Enable - r |= XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS; // Tx & Rx Disable - UART_CTRL = r; - - UART_MODE = 0; - UART_MODE &= ~XUARTPS_MR_CLKSEL; // Clear "Input clock selection" - 0: clock source is uart_ref_clk - UART_MODE |= XUARTPS_MR_CHARLEN_8_BIT; // Set "8 bits data" - UART_MODE |= XUARTPS_MR_PARITY_NONE; // Set "No parity mode" - UART_MODE |= XUARTPS_MR_STOPMODE_1_BIT; // Set "1 stop bit" - UART_MODE |= XUARTPS_MR_CHMODE_NORM; // Set "Normal mode" - - // baud_rate = sel_clk / (CD * (BDIV + 1) (ref: UG585 - TRM - Ch. 19 UART) - UART_BAUD_DIV = 6; // ("BDIV") - UART_BAUD_GEN = 124; // ("CD") - // Baud Rate = 100Mhz / (124 * (6 + 1)) = 115200 bps - - UART_CTRL |= (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); // TX & RX logic reset - - r = UART_CTRL; - r |= XUARTPS_CR_RX_EN | XUARTPS_CR_TX_EN; // Set TX & RX enabled - r &= ~(XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS); // Clear TX & RX disabled - UART_CTRL = r; - - while(1) { - // Count to big number before exiting for loop - delay loop - for(uint32_t i = 1; i < (1 << 20); i++){ - uart_receive(); // polling UART receive buffer - } - - static char c = '0'; - uart_send(c++); // Send and increment character variable c - // If incremented over 'Z', initialize to '0' (ref: see ASCII character table) - if (c > 'Z') c = '0'; - uart_send_string(str); // Send character array variable str - - } +void uart_setup(void) { + uint32_t r = 0; // Temporary value variable + r = UART_CTRL; + r &= ~(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN); // Clear Tx & Rx Enable + r |= XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS; // Tx & Rx Disable + UART_CTRL = r; + + UART_MODE = 0; + UART_MODE &= ~XUARTPS_MR_CLKSEL; // Clear "Input clock selection" - 0: clock source is uart_ref_clk + UART_MODE |= XUARTPS_MR_CHARLEN_8_BIT; // Set "8 bits data" + UART_MODE |= XUARTPS_MR_PARITY_NONE; // Set "No parity mode" + UART_MODE |= XUARTPS_MR_STOPMODE_1_BIT; // Set "1 stop bit" + UART_MODE |= XUARTPS_MR_CHMODE_NORM; // Set "Normal mode" + + // baud_rate = sel_clk / (CD * (BDIV + 1) (ref: UG585 - TRM - Ch. 19 UART) + UART_BAUD_DIV = 6; // ("BDIV") + UART_BAUD_GEN = 124; // ("CD") + // Baud Rate = 100Mhz / (124 * (6 + 1)) = 115200 bps + + UART_CTRL |= (XUARTPS_CR_TXRST | XUARTPS_CR_RXRST); // TX & RX logic reset + + r = UART_CTRL; + r |= XUARTPS_CR_RX_EN | XUARTPS_CR_TX_EN; // Set TX & RX enabled + r &= ~(XUARTPS_CR_RX_DIS | XUARTPS_CR_TX_DIS); // Clear TX & RX disabled + UART_CTRL = r; +} + +void gpio_setup() { + MIO_PIN07_CTRL = MIO_PIN07_CTRL_GPIO0; + + GPIO_DIRM0 |= GPIO0_PIN7; + GPIO_OEN0 |= GPIO0_PIN7; +} + +static inline void led_toggle() { + GPIO_DATA0 ^= GPIO0_PIN7; +} + +/* back up the cursor one space */ +static inline void back_up(void) +{ + end_ndx = dec_ndx(end_ndx); + uart_send('\010'); + uart_send(' '); + uart_send('\010'); +} + +/* + * A buffered line editing function. + */ +void +get_buffered_line(void) { + char c; + + if (start_ndx != end_ndx) { + return; + } + while (1) { + c = uart_recv_blocking(); + if (c == '\r') { + buf[end_ndx] = '\n'; + end_ndx = inc_ndx(end_ndx); + buf[end_ndx] = '\0'; + uart_send('\r'); + uart_send('\n'); + return; + } + /* ^H or DEL erase a character */ + if ((c == '\010') || (c == '\177')) { + if (buf_len == 0) { + uart_send('\a'); + } else { + back_up(); + } + /* ^W erases a word */ + } else if (c == 0x17) { + while ((buf_len > 0) && + (!(isspace((int) buf[end_ndx])))) { + back_up(); + } + /* ^U erases the line */ + } else if (c == 0x15) { + while (buf_len > 0) { + back_up(); + } + /* Non-editing character so insert it */ + } else { + if (buf_len == (BUFLEN - 1)) { + uart_send('\a'); + } else { + buf[end_ndx] = c; + end_ndx = inc_ndx(end_ndx); + uart_send(c); + } + } + } +} + +/* + * Called by libc stdio fwrite functions + */ +int +_write(int fd, char *ptr, int len) +{ + int i = 0; + + /* + * Write "len" of char from "ptr" to file id "fd" + * Return number of char written. + * + * Only work for STDOUT, STDIN, and STDERR + */ + if (fd > 2) { + return -1; + } + while (*ptr && (i < len)) { + uart_send(*ptr); + if (*ptr == '\n') { + uart_send('\r'); + } + i++; + ptr++; + } + return i; +} + +/* + * Called by the libc stdio fread fucntions + * + * Implements a buffered read with line editing. + */ +int +_read(int fd, char *ptr, int len) +{ + int my_len; + + if(fd > 2) + return -1; + + get_buffered_line(); + my_len = 0; + while ((buf_len > 0) && (len > 0)) { + *ptr++ = buf[start_ndx]; + start_ndx = inc_ndx(start_ndx); + my_len++; + len--; + } + return my_len; /* return the length we got */ +} + +int get_delay() { + char local_buf[32]; + printf("Enter the delay constant for blink: "); + fflush(stdout); + fgets(local_buf, sizeof(local_buf), stdin); + return atoi(local_buf); +} + +static inline void led_blink(int delay) { + int i; + while(1) { + led_toggle(); + + for (i = 0; i < delay; i++); + + if(uart_recv() == 0x3) // ^C + break; + } +} + +int main(void) +{ + int delay = 0; + + uart_setup(); + gpio_setup(); + + printf("\nStandard I/O Example.\n"); + + while(1) { + delay = get_delay(); + printf("Blinking with a delay of %d\n", delay); + led_blink(delay); + } + + return 0; } |