|
| 1 | +// Copyright (c) 2025 Cesanta Software Limited |
| 2 | +// SPDX-License-Identifier: MIT |
| 3 | + |
| 4 | +#pragma once |
| 5 | + |
| 6 | +#include <stdbool.h> |
| 7 | +#include <stdint.h> |
| 8 | +#include <stdio.h> |
| 9 | +#include <string.h> |
| 10 | + |
| 11 | +#include "MCXW716C.h" |
| 12 | +#include "MCXW716C_COMMON.h" |
| 13 | + |
| 14 | +#define BIT(x) (1UL << (x)) |
| 15 | +#define CLRSET(R, CLEARMASK, SETMASK) (R) = ((R) & ~(CLEARMASK)) | (SETMASK) |
| 16 | +#define PIN(bank, num) ((((bank) - 'A') << 8) | (num)) |
| 17 | +#define PINNO(pin) (pin & 255) |
| 18 | +#define PINBANK(pin) (pin >> 8) |
| 19 | + |
| 20 | +#define SYS_FREQUENCY 6000000 |
| 21 | + |
| 22 | +static inline void spin(volatile uint32_t count) { |
| 23 | + while (count--) (void) 0; |
| 24 | +} |
| 25 | + |
| 26 | +enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG }; |
| 27 | +enum { GPIO_OTYPE_PUSH_PULL, GPIO_OTYPE_OPEN_DRAIN }; |
| 28 | +enum { GPIO_SPEED_LOW, GPIO_SPEED_MEDIUM, GPIO_SPEED_HIGH, GPIO_SPEED_INSANE }; |
| 29 | +enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN }; |
| 30 | + |
| 31 | +static inline GPIO_Type *gpio_bank(uint16_t pin) { |
| 32 | + uint8_t bank = PINBANK(pin); |
| 33 | + return (GPIO_Type *) (bank == 0 ? GPIOA |
| 34 | + : bank == 1 ? GPIOB |
| 35 | + : bank == 2 ? GPIOC |
| 36 | + : bank == 3 ? GPIOD |
| 37 | + : 0); |
| 38 | +} |
| 39 | + |
| 40 | +static inline void gpio_toggle(uint16_t pin) { |
| 41 | + GPIO_Type *gpio = gpio_bank(pin); |
| 42 | + gpio->PTOR |= BIT(PINNO(pin)); |
| 43 | +} |
| 44 | + |
| 45 | +static inline bool gpio_read(uint16_t pin) { |
| 46 | + GPIO_Type *gpio = gpio_bank(pin); |
| 47 | + return gpio->PDR[PINNO(pin)]; |
| 48 | +} |
| 49 | + |
| 50 | +static inline void gpio_write(uint16_t pin, bool val) { |
| 51 | + GPIO_Type *gpio = gpio_bank(pin); |
| 52 | + if (val) { |
| 53 | + // gpio->PSOR |= BIT(PINNO(pin)); |
| 54 | + gpio->PDR[PINNO(pin)] = 1U; |
| 55 | + } else { |
| 56 | + // gpio->PCOR |= BIT(PINNO(pin)); |
| 57 | + gpio->PDR[PINNO(pin)] = 0; |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type, |
| 62 | + uint8_t speed, uint8_t pull, uint8_t af) { |
| 63 | + GPIO_Type *gpio = gpio_bank(pin); |
| 64 | + (void) pin, (void) mode, (void) type, (void) speed, (void) pull, (void) af; |
| 65 | +#if 0 |
| 66 | + if (gpio == GPIOA) { |
| 67 | + CLRSET(MRCC->MRCC_GPIOA, MRCC_MRCC_GPIOA_CC_MASK, 1U); |
| 68 | + } else if (gpio == GPIOB) { |
| 69 | + CLRSET(MRCC->MRCC_GPIOB, MRCC_MRCC_GPIOB_CC_MASK, 1U); |
| 70 | + } else if (gpio == GPIOC) { |
| 71 | + CLRSET(MRCC->MRCC_GPIOC, MRCC_MRCC_GPIOC_CC_MASK, 1U); |
| 72 | + } |
| 73 | + __ISB(); |
| 74 | + __DSB(); |
| 75 | +#endif |
| 76 | + if (mode == GPIO_MODE_OUTPUT) { |
| 77 | + // gpio->PDOR &= ~BIT(PINNO(pin)); |
| 78 | + gpio->PDOR |= BIT(PINNO(pin)); |
| 79 | + gpio->PDDR |= BIT(PINNO(pin)); |
| 80 | + } else { |
| 81 | + gpio->PDDR &= ~BIT(PINNO(pin)); |
| 82 | + } |
| 83 | +} |
| 84 | +static inline void gpio_input(uint16_t pin) { |
| 85 | + gpio_init(pin, GPIO_MODE_INPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, |
| 86 | + GPIO_PULL_NONE, 0); |
| 87 | +} |
| 88 | +static inline void gpio_output(uint16_t pin) { |
| 89 | + gpio_init(pin, GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, |
| 90 | + GPIO_PULL_NONE, 0); |
| 91 | +} |
| 92 | + |
| 93 | +static inline void uart_init(LPUART_Type *uart, unsigned long baud) { |
| 94 | + uint32_t val = 0x80000000U; // Module present |
| 95 | + val |= 0x40000000U; // Release from reset |
| 96 | + val |= 1U; // Enable clock |
| 97 | + val |= 2U << 4; // Clock mux: FRO-6M |
| 98 | + if (uart == LPUART0) { |
| 99 | + MRCC->MRCC_LPUART0 = val; |
| 100 | + } else if (uart == LPUART1) { |
| 101 | + MRCC->MRCC_LPUART1 = val; |
| 102 | + } |
| 103 | + (void) baud; |
| 104 | +} |
| 105 | + |
| 106 | +static inline void uart_write_byte(LPUART_Type *uart, uint8_t byte) { |
| 107 | + // while ((uart->FIFOSTAT & UART_FIFOSTAT_TXNOTFULL_MASK) == 0) spin(1); |
| 108 | + return; |
| 109 | + uart->FIFO = byte; |
| 110 | +} |
| 111 | +static inline void uart_write_buf(LPUART_Type *uart, char *buf, size_t len) { |
| 112 | + while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++); |
| 113 | +} |
| 114 | + |
| 115 | +// t: expiration time, prd: period, now: current time. Return true if expired |
| 116 | +static inline bool timer_expired(volatile uint64_t *t, uint64_t prd, |
| 117 | + uint64_t now) { |
| 118 | + if (now + prd < *t) *t = 0; // Time wrapped? Reset timer |
| 119 | + if (*t == 0) *t = now + prd; // Firt poll? Set expiration |
| 120 | + if (*t > now) return false; // Not expired yet, return |
| 121 | + *t = (now - *t) > prd ? now + prd : *t + prd; // Next expiration time |
| 122 | + return true; // Expired, return true |
| 123 | +} |
0 commit comments