/* * The MIT License (MIT) * * Copyright (c) 2021, Koji Kitayama * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * This file is part of the TinyUSB stack. */ /* How to connect JLink and RX65n Target and option board * (For original comment https://github.com/hathach/tinyusb/pull/922#issuecomment-869786131) * * To enable JTAG, RX65N requires following connections on main board. * - short EJ2 jumper header, to disable onboard E2L. * - short EMLE(J1-2) and 3V3(J1-14 or J2-10), to enable In-Circuit Emulator. * * Note: For RX65N-Cloud-Kit, the option board's JTAG pins to some switches or floating. * To use JLink with the option board, I think some further modifications will be necessary. * * | Function | RX65N pin | main board | option board | JLink connector | * |:---------:|:----------:|:----------:|:------------:|:---------------:| * | 3V3 | VCC | J1-14 | CN5-6 | 1 | * | TRST | P34 | J1-16 | CN5-7 | 3 | * | GND | VSS | J1-12 | CN5-5 | 4 | * | TDI | P30 | J1-20 | CN5-10 | 5 | * | TMS | P31 | J1-19 | USER_SW | 7 | * | TCK/FINEC | P27 | J1-21 | N/A | 9 | * | TDO | P26 | J1-22 | CN5-9 | 13 | * | nRES | RES# | J1-10 | RESET_SW | 15 | * * JLink firmware needs to update to V6.96 or newer version to avoid * [a bug](https://forum.segger.com/index.php/Thread/7758-SOLVED-Bug-in-JLink-from-V6-88b-regarding-RX65N) * regarding downloading. */ #include "bsp/board.h" #include "iodefine.h" #include "interrupt_handlers.h" #define IRQ_PRIORITY_CMT0 5 #define IRQ_PRIORITY_USBI0 6 #define IRQ_PRIORITY_SCI5 5 #define SYSTEM_PRCR_PRC1 (1<<1) #define SYSTEM_PRCR_PRKEY (0xA5u<<8) #define CMT_PCLK 60000000 #define CMT_CMCR_CKS_DIV_128 2 #define CMT_CMCR_CMIE (1<<6) #define MPC_PFS_ISEL (1<<6) #define SCI_PCLK 60000000 #define SCI_SSR_FER (1<<4) #define SCI_SSR_ORER (1<<5) #define SCI_SCR_TEIE (1u<<2) #define SCI_SCR_RE (1u<<4) #define SCI_SCR_TE (1u<<5) #define SCI_SCR_RIE (1u<<6) #define SCI_SCR_TIE (1u<<7) #define INT_Excep_SCI5_TEI5 INT_Excep_ICU_GROUPBL0 #define IRQ_USB0_USBI0 62 #define SLIBR_USBI0 SLIBR185 #define IPR_USB0_USBI0 IPR_PERIB_INTB185 #define INT_Excep_USB0_USBI0 INT_Excep_PERIB_INTB185 void HardwareSetup(void) { FLASH.ROMCIV.WORD = 1; while (FLASH.ROMCIV.WORD) ; FLASH.ROMCE.WORD = 1; while (!FLASH.ROMCE.WORD) ; SYSTEM.PRCR.WORD = 0xA503u; if (!SYSTEM.RSTSR1.BYTE) { RTC.RCR4.BYTE = 0; RTC.RCR3.BYTE = 12; while (12 != RTC.RCR3.BYTE) ; } SYSTEM.SOSCCR.BYTE = 1; if (SYSTEM.HOCOCR.BYTE) { SYSTEM.HOCOCR.BYTE = 0; while (!SYSTEM.OSCOVFSR.BIT.HCOVF) ; } SYSTEM.PLLCR.WORD = 0x1D10u; /* HOCO x 15 */ SYSTEM.PLLCR2.BYTE = 0; while (!SYSTEM.OSCOVFSR.BIT.PLOVF) ; SYSTEM.SCKCR.LONG = 0x21C11222u; SYSTEM.SCKCR2.WORD = 0x0041u; SYSTEM.ROMWT.BYTE = 0x02u; while (0x02u != SYSTEM.ROMWT.BYTE) ; SYSTEM.SCKCR3.WORD = 0x400u; SYSTEM.PRCR.WORD = 0xA500u; } //--------------------------------------------------------------------+ // SCI handling //--------------------------------------------------------------------+ typedef struct { uint8_t *buf; uint32_t cnt; } sci_buf_t; static volatile sci_buf_t sci_buf[2]; void INT_Excep_SCI5_TXI5(void) { uint8_t *buf = sci_buf[0].buf; uint32_t cnt = sci_buf[0].cnt; if (!buf || !cnt) { SCI5.SCR.BYTE &= ~(SCI_SCR_TEIE | SCI_SCR_TE | SCI_SCR_TIE); return; } SCI5.TDR = *buf; if (--cnt) { ++buf; } else { buf = NULL; SCI5.SCR.BIT.TIE = 0; SCI5.SCR.BIT.TEIE = 1; } sci_buf[0].buf = buf; sci_buf[0].cnt = cnt; } void INT_Excep_SCI5_TEI5(void) { SCI5.SCR.BYTE &= ~(SCI_SCR_TEIE | SCI_SCR_TE | SCI_SCR_TIE); } void INT_Excep_SCI5_RXI5(void) { uint8_t *buf = sci_buf[1].buf; uint32_t cnt = sci_buf[1].cnt; if (!buf || !cnt || (SCI5.SSR.BYTE & (SCI_SSR_FER | SCI_SSR_ORER))) { sci_buf[1].buf = NULL; SCI5.SSR.BYTE = 0; SCI5.SCR.BYTE &= ~(SCI_SCR_RE | SCI_SCR_RIE); return; } *buf = SCI5.RDR; if (--cnt) { ++buf; } else { buf = NULL; SCI5.SCR.BYTE &= ~(SCI_SCR_RE | SCI_SCR_RIE); } sci_buf[1].buf = buf; sci_buf[1].cnt = cnt; } //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ void INT_Excep_USB0_USBI0(void) { #if CFG_TUH_ENABLED tuh_int_handler(0); #endif #if CFG_TUD_ENABLED tud_int_handler(0); #endif } void board_init(void) { /* setup software configurable interrupts */ ICU.SLIBR_USBI0.BYTE = IRQ_USB0_USBI0; ICU.SLIPRCR.BYTE = 1; #if CFG_TUSB_OS == OPT_OS_NONE /* Enable CMT0 */ SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; MSTP(CMT0) = 0; SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; /* Setup 1ms tick timer */ CMT0.CMCNT = 0; CMT0.CMCOR = CMT_PCLK / 1000 / 128; CMT0.CMCR.WORD = CMT_CMCR_CMIE | CMT_CMCR_CKS_DIV_128; IR(CMT0, CMI0) = 0; IPR(CMT0, CMI0) = IRQ_PRIORITY_CMT0; IEN(CMT0, CMI0) = 1; CMT.CMSTR0.BIT.STR0 = 1; #endif /* Unlock MPC registers */ MPC.PWPR.BIT.B0WI = 0; MPC.PWPR.BIT.PFSWE = 1; // SW PB1 PORTB.PMR.BIT.B1 = 0U; PORTB.PDR.BIT.B1 = 0U; // LED PD6 PORTD.PODR.BIT.B6 = 1U; PORTD.ODR1.BIT.B4 = 1U; PORTD.PMR.BIT.B6 = 0U; PORTD.PDR.BIT.B6 = 1U; /* UART TXD5 => PA4, RXD5 => PA3 */ PORTA.PMR.BIT.B4 = 1U; PORTA.PCR.BIT.B4 = 1U; MPC.PA4PFS.BYTE = 0b01010; PORTA.PMR.BIT.B3 = 1U; MPC.PA5PFS.BYTE = 0b01010; /* USB VBUS -> P16 */ PORT1.PMR.BIT.B6 = 1U; MPC.P16PFS.BYTE = MPC_PFS_ISEL | 0b10001; /* Lock MPC registers */ MPC.PWPR.BIT.PFSWE = 0; MPC.PWPR.BIT.B0WI = 1; /* Enable SCI5 */ SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1; MSTP(SCI5) = 0; SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY; SCI5.SEMR.BIT.ABCS = 1; SCI5.SEMR.BIT.BGDM = 1; SCI5.BRR = (SCI_PCLK / (8 * 115200)) - 1; IR(SCI5, RXI5) = 0; IR(SCI5, TXI5) = 0; IS(SCI5, TEI5) = 0; IR(ICU, GROUPBL0) = 0; IPR(SCI5, RXI5) = IRQ_PRIORITY_SCI5; IPR(SCI5, TXI5) = IRQ_PRIORITY_SCI5; IPR(ICU,GROUPBL0) = IRQ_PRIORITY_SCI5; IEN(SCI5, RXI5) = 1; IEN(SCI5, TXI5) = 1; IEN(ICU,GROUPBL0) = 1; EN(SCI5, TEI5) = 1; /* setup USBI0 interrupt. */ IR(USB0, USBI0) = 0; IPR(USB0, USBI0) = IRQ_PRIORITY_USBI0; } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ void board_led_write(bool state) { PORTD.PODR.BIT.B6 = state ? 0 : 1; } uint32_t board_button_read(void) { return PORTB.PIDR.BIT.B1 ? 0 : 1; } int board_uart_read(uint8_t* buf, int len) { sci_buf[1].buf = buf; sci_buf[1].cnt = len; SCI5.SCR.BYTE |= SCI_SCR_RE | SCI_SCR_RIE; while (SCI5.SCR.BIT.RE) ; return len - sci_buf[1].cnt; } int board_uart_write(void const *buf, int len) { sci_buf[0].buf = (uint8_t*)(uintptr_t) buf; sci_buf[0].cnt = len; SCI5.SCR.BYTE |= SCI_SCR_TE | SCI_SCR_TIE; while (SCI5.SCR.BIT.TE) ; return len; } #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; void INT_Excep_CMT0_CMI0(void) { ++system_ticks; } uint32_t board_millis(void) { return system_ticks; } #else uint32_t SystemCoreClock = 120000000; #endif int close(int fd) { (void)fd; return -1; } int fstat(int fd, void *pstat) { (void)fd; (void)pstat; return 0; } off_t lseek(int fd, off_t pos, int whence) { (void)fd; (void)pos; (void)whence; return 0; } int isatty(int fd) { (void)fd; return 1; }