/*********************************************************************************************************************** * DISCLAIMER * This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. * No other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all * applicable laws, including copyright laws. * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED * OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY * LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE FOR ANY DIRECT, * INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR * ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability * of this software. By using this software, you agree to the additional terms and conditions found by accessing the * following link: * http://www.renesas.com/disclaimer * * Copyright (C) 2012, 2021 Renesas Electronics Corporation. All rights reserved. ***********************************************************************************************************************/ /*********************************************************************************************************************** * File Name : r_main.c * Version : CodeGenerator for RL78/F14 V2.03.07.02 [08 Nov 2021] * Device(s) : R5F10PPJ * Tool-Chain : CCRL * Description : main + UART protocol handler * Creation Date: 2026-01-29 ***********************************************************************************************************************/ /*********************************************************************************************************************** Includes ***********************************************************************************************************************/ #include "r_cg_macrodriver.h" #include "r_cg_cgc.h" #include "r_cg_port.h" #include "r_cg_serial.h" /* Start user code for include. Do not edit comment generated here */ #include "common.h" #include "dipSwitch.h" #include "gatectrl.h" #include #include #include #include #include /* End user code. Do not edit comment generated here */ #include "r_cg_userdefine.h" /* Start user code for adding. Do not edit comment generated here */ /* ========================= * Config * ========================= */ #define CMD_MAX 529 #define UART_RX_BUF_SIZE 1024 #define RS485_BRIDGE_FIFO_SZ 2048 #define BRIDGE_IDLE_DONE_US 5000U // ¸¶Áö¸· ¹ÙÀÌÆ® ÀÌÈÄ 3ms Á¶¿ëÇϸé Á¾·á·Î ÆÇ´Ü #define BRIDGE_TOTAL_WAIT_US 600000U /* ========================= * UART RX Buffers * ========================= */ volatile uint8_t uart_rx_done = 0; volatile uint16_t uart_rx_index = 0; // ¡Ú uint8_t -> uint16_t volatile uint8_t uart_rx_buffer[UART_RX_BUF_SIZE] = {0}; volatile uint16_t uart_rx_length = 0; volatile uint8_t rs485_rx_done = 0; volatile uint8_t rs485_rx_index = 0; volatile uint8_t rs485_rx_buffer[UART_RX_BUF_SIZE] = {0}; volatile uint16_t rs485_rx_length = 0; volatile uint32_t g_uart0_err_fef = 0; volatile uint32_t g_uart0_err_ovf = 0; volatile uint32_t g_uart0_err_pef = 0; /* RS485 bridge flags */ volatile uint8_t g_rs485_bridge_active = 0; volatile uint8_t g_rs485_bridge_done = 0; volatile uint16_t g_rs485_bridge_seq = 0; static volatile uint8_t s_end_st = 0; static const char s_end_pat[] = ""; /* (0~31) */ uint8_t g_fixed_addr = 0; /* ========================= * Driver globals (Renesas) * ========================= */ extern volatile uint16_t g_uart1_tx_count; /* UART1 TX ÁøÇà Ä«¿îÆ® */ extern volatile uint16_t g_uart0_tx_count; /* UART0 TX ÁøÇà Ä«¿îÆ® */ extern volatile uint8_t g_uart0_tx_done; /* ========================= * RS485 Bridge FIFO * ========================= */ static volatile uint8_t s_rb_fifo[RS485_BRIDGE_FIFO_SZ]; static volatile uint16_t s_rb_head = 0; static volatile uint16_t s_rb_tail = 0; void RS485_Bridge_Push(uint8_t b) { uint16_t next = (uint16_t)(s_rb_head + 1); if (next >= RS485_BRIDGE_FIFO_SZ) next = 0; if (next == s_rb_tail) { uint16_t t = (uint16_t)(s_rb_tail + 1); if (t >= RS485_BRIDGE_FIFO_SZ) t = 0; s_rb_tail = t; } s_rb_fifo[s_rb_head] = b; s_rb_head = next; } static void RS485_Bridge_ResetFifo(void) { s_rb_head = 0; s_rb_tail = 0; s_end_st = 0; g_rs485_bridge_done = 0; } static int RS485_Bridge_ReadLine(char *out, int out_sz, uint32_t timeout_us) { int n = 0; while (timeout_us--) { // FIFO¿¡ µ¥ÀÌÅͰ¡ ÀÖÀ¸¸é 1¹ÙÀÌÆ®¾¿ ²¨³»¼­ line ±¸¼º while (s_rb_tail != s_rb_head) { char c = (char)s_rb_fifo[s_rb_tail]; s_rb_tail++; if (s_rb_tail >= RS485_BRIDGE_FIFO_SZ) s_rb_tail = 0; if (c == '\r') continue; if (n < out_sz - 1) out[n++] = c; if (c == '\n') { out[n] = '\0'; return 1; // line ¿Ï¼º } } delay_us(1); } if (n > 0) { out[n] = '\0'; } return 0; // timeout } static int Is_V_Response_For(char *line, uint8_t addr) { uint8_t a; // line ¿¹: "V02\n" ¶Ç´Â "V02\r\n" (CRÀº À§¿¡¼­ Á¦°ÅµÊ) if (line[0] != 'V' && line[0] != 'v') return 0; if (!isdigit((unsigned char)line[1]) || !isdigit((unsigned char)line[2])) return 0; a = (uint8_t)((line[1]-'0')*10 + (line[2]-'0')); return (a == addr); } /* ========================= * ? PC(UART1) Safe TX (Áß¿ä) * - ·ÎÄà ¹öÆÛ ±ÝÁö * - Ç×»ó Àü¿ª ¹öÆÛ·Î º¹»ç ÈÄ R_UART1_Send * ========================= */ static uint8_t g_uart1_txbuf[512]; static void UART1_WaitTxIdle(void) { unsigned long guard = 0; while (g_uart1_tx_count != 0U) { if (guard++ > 3000000UL) break; /* ¹«ÇÑ·çÇÁ ¹æÁö */ } } static void UART1_SendBytes_Safe(const uint8_t *data, uint16_t len) { if (data == 0 || len == 0) return; UART1_WaitTxIdle(); if (len > (uint16_t)sizeof(g_uart1_txbuf)) len = (uint16_t)sizeof(g_uart1_txbuf); memcpy(g_uart1_txbuf, data, len); R_UART1_Send(g_uart1_txbuf, len); UART1_WaitTxIdle(); } static void UART1_SendString_Safe(const char *s) { uint16_t len; if (s == 0) return; UART1_WaitTxIdle(); // ? º¸³»±â Àü ´ë±â len = (uint16_t)strlen(s); if (len >= (uint16_t)sizeof(g_uart1_txbuf)) len = (uint16_t)(sizeof(g_uart1_txbuf) - 1); memcpy(g_uart1_txbuf, s, len); g_uart1_txbuf[len] = '\0'; R_UART1_Send(g_uart1_txbuf, len); UART1_WaitTxIdle(); // ? ¡Ú Ãß°¡: º¸³»°í ³­ µÚ¿¡µµ ´ë±â (¹öÆÛ µ¤¾î¾²±â ¹æÁö) } /* ========================= * RS485 Bridge Drain -> PC * - uart1_send_string(out) °°Àº 1¹ÙÀÌÆ® ¹®ÀÚ¿­ ¼Û½Å ±ÝÁö * - UART1_SendBytes_Safe·Î ÇÑ ¹ÙÀÌÆ®¾¿ÀÌ¶óµµ "¾ÈÀüÇϰÔ" Àü¼Û * ========================= */ static void RS485_Bridge_DrainToPC(void) { uint16_t n = 0; /* UART1ÀÌ TXÁßÀÌ¸é ´ÙÀ½ ·çÇÁ¿¡¼­ */ if (g_uart1_tx_count != 0U) return; /* FIFO -> Àӽà ¹öÆÛ¿¡ ÃÖ´ë 64¹ÙÀÌÆ®±îÁö ¸ð¾Æ¼­ ÇÑ ¹ø¿¡ Àü¼Û */ while (s_rb_tail != s_rb_head && n < 256U) { g_uart1_txbuf[n++] = s_rb_fifo[s_rb_tail]; s_rb_tail++; if (s_rb_tail >= RS485_BRIDGE_FIFO_SZ) s_rb_tail = 0; } if (n > 0) { R_UART1_Send(g_uart1_txbuf, n); } } /* ========================= * Helpers * ========================= */ static unsigned char hex2byte(char h, char l) { unsigned char hi, lo; if (h >= 'a' && h <= 'f') h -= 32; if (l >= 'a' && l <= 'f') l -= 32; hi = (h >= 'A') ? (unsigned char)(h - 'A' + 10) : (unsigned char)(h - '0'); lo = (l >= 'A') ? (unsigned char)(l - 'A' + 10) : (unsigned char)(l - '0'); return (unsigned char)((hi << 4) | lo); } /* ========================= * Prefix mode * ========================= */ typedef enum { PREFIX_NONE = 0, PREFIX_CAL, PREFIX_EOL } PrefixMode; static PrefixMode s_prefix_mode = PREFIX_NONE; /* ========================= * parse x-prefix: xNNc_001011:... * ========================= */ static int parse_x_prefix(const char *s, int len, uint8_t *addr, uint8_t *ch, char *mode, uint8_t *hash_on, uint8_t *anaout_on, uint8_t *check_on, int *payload_pos) { if (len < 8) return 0; if (!(s[0] == 'x' || s[0] == 'X')) return 0; if (!isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) return -1; if (s[3] == 'c' || s[3] == 'C') *mode = 'C'; else if (s[3] == 'e' || s[3] == 'E') *mode = 'E'; else return -1; if (s[4] != '_') return -1; if (!isdigit((unsigned char)s[5]) || !isdigit((unsigned char)s[6]) || !isdigit((unsigned char)s[7])) return -1; *addr = (uint8_t)((s[1] - '0') * 10 + (s[2] - '0')); *ch = (uint8_t)((s[5] - '0') * 100 + (s[6] - '0') * 10 + (s[7] - '0')); /* prefix only: x01c_001 */ if (len == 8) { *payload_pos = len; return 1; } /* payload: x01c_001:... */ if (s[8] == ':') { *payload_pos = 9; return 1; } /* flags: x01c_001011 or x01c_001011:... */ if (len >= 11 && (s[8] == '0' || s[8] == '1') && (s[9] == '0' || s[9] == '1') && (s[10] == '0' || s[10] == '1')) { *hash_on = (uint8_t)(s[8] - '0'); *anaout_on = (uint8_t)(s[9] - '0'); *check_on = (uint8_t)(s[10] - '0'); if (len == 11) { *payload_pos = 11; return 1; } if (len >= 12 && s[11] == ':') { *payload_pos = 12; return 1; } return -1; } return -1; } static int bridge_wait_until_end(uint32_t total_us) { const char *pat = ""; uint8_t st = 0; while (total_us--) { // FIFO -> PC Àü¼Û while (s_rb_tail != s_rb_head) { char c = (char)s_rb_fifo[s_rb_tail]; s_rb_tail = (s_rb_tail + 1) % RS485_BRIDGE_FIFO_SZ; // PC·Î ¹Ù·Î Ãâ·Â(¹öÆÛ¸µÀº ±âÁ¸Ã³·³ ¸ð¾Æ¼­ º¸³»µµ OK) // ¿©±â¼­´Â ´Ü¼øÈ­¸¦ À§ÇØ 1¹ÙÀÌÆ®¶ó °¡Á¤ÇÏÁö ¸»°í ±âÁ¸ 256¸ð¾Æ¼­ º¸³»´Â ÇÔ¼ö À¯Áö ±ÇÀå // ÆÐÅÏ ¸ÅĪ if (c == pat[st]) { st++; if (pat[st] == 0) return 1; // found } else { st = (c == pat[0]) ? 1 : 0; } } delay_us(1); } return 0; } /* ========================= * Print routing * ========================= */ typedef enum { CMD_SRC_PC = 0, CMD_SRC_RS485 = 1 } CmdSource; /* ? PC Ãâ·ÂÀº ¹«Á¶°Ç Safe·Î */ static void OUT_PRINT(CmdSource src, const char *s) { if (src == CMD_SRC_PC) { UART1_SendString_Safe(s); } else { /* RS485_PRINT´Â ³× ÇÁ·ÎÁ§Æ® ±âÁ¸ ÇÔ¼ö(º¸Åë UART0 TX) */ RS485_PRINT(s); } } static void send_end_response(void) { OUT_PRINT(CMD_SRC_PC, "\r\n"); } /* ========================= * xNNv command * ========================= */ static int parse_x_v_cmd(const char *s, int len, uint8_t *addr) { if (len != 4) return 0; if (!(s[0] == 'x' || s[0] == 'X')) return 0; if (!isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) return 0; if (!(s[3] == 'v' || s[3] == 'V')) return 0; *addr = (uint8_t)((s[1] - '0') * 10 + (s[2] - '0')); return 1; } static void send_n_response(uint8_t addr) { char resp[8]; resp[0] = 'N'; resp[1] = (char)('0' + (addr / 10)); resp[2] = (char)('0' + (addr % 10)); resp[3] = '\r'; resp[4] = '\n'; resp[5] = '\0'; OUT_PRINT(CMD_SRC_PC, resp); } static int parse_x_o_cmd(const char *s, int len, uint8_t *addr) { if (len != 4) return 0; if (!(s[0] == 'x' || s[0] == 'X')) return 0; if (!isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) return 0; if (!(s[3] == 'o' || s[3] == 'O')) return 0; *addr = (uint8_t)((s[1]-'0')*10 + (s[2]-'0')); return 1; } /* ? ¿©±â¼­µµ OUT_PRINT°¡ Safe¸¦ Ÿ¹Ç·Î ±úÁü ¾øÀ½ */ static void send_v_response(CmdSource src, uint8_t addr) { char resp[8]; resp[0] = 'V'; resp[1] = (char)('0' + (addr / 10)); resp[2] = (char)('0' + (addr % 10)); resp[3] = '\r'; resp[4] = '\n'; resp[5] = '\0'; if (src == CMD_SRC_RS485) { delay_us(600); // 200~500us ±ÇÀå (ȯ°æ µû¶ó Á¶Á¤) } OUT_PRINT(src, resp); } static void UART0_WaitTxDone_Flag(uint32_t guard_us) { while (!g_uart0_tx_done && guard_us--) { delay_us(1); } } static void RS485_FlushJunk(uint16_t loops, uint16_t step_us) { // ½ºÄµ ½ÃÀÛ Àü¿¡, µé¾î¿Í ÀÖ´ø CR/LF/³ëÀÌÁ PC·Î »©°í FIFOµµ ºñ¿ò while (loops--) { RS485_Bridge_DrainToPC(); delay_us(step_us); } } static void PC_PrintLine_CRLF(const char *line) { char tmp[40]; size_t n = strlen(line); size_t i; // lineÀÌ '\n'·Î ³¡³ª¸é, "\r\n"·Î º¸Á¤ if (n > 0 && line[n-1] == '\n') { size_t m = 0; for (i=0; i 0) { /* 0.5ms¾¿ ²÷¾î º¸±â */ int got = RS485_Bridge_ReadLine(linebuf, sizeof(linebuf), 500); if (got) { if (Is_V_Response_For(linebuf, addr)) { PC_PrintLine_CRLF(linebuf); g_rs485_bridge_active = 0; return; } /* ´Ù¸¥ ¶óÀÎ(¾²·¹±â/¿¡ÄÚ)¸é °è¼Ó */ } total_wait_us -= 500; } } g_rs485_bridge_active = 0; } // ½ÇÆÐ ¿øÀÎÀÌ ¿¡·¯/²¿ÀÓÀÌ¸é º¹±¸ ÈÄ Àç½Ãµµ if (g_rs485_need_recover) { rs485_recover(); } delay_us(500); } /* ½ÇÆÐ ½Ã Nxx */ send_n_response(addr); /* ´ÙÀ½À» À§ÇØ RX Àçarm */ rs485_rx_done = 0; rs485_rx_index = 0; rs485_rx_length = 0; R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1); } /* ========================= * Build line from rx buffer * ========================= */ static int build_line_from_rx(const volatile uint8_t *rx_buf, int rx_len, char *out, int out_sz) { int i, idx = 0; if (rx_len < 0) rx_len = 0; if (rx_len > out_sz - 1) rx_len = out_sz - 1; for (i = 0; i < rx_len && idx < out_sz - 1; i++) { char c = (char)rx_buf[i]; if (c == '\r') continue; if (c == '\n') break; out[idx++] = c; } out[idx] = '\0'; return idx; } /* ========================= * Protocol detect * ========================= */ typedef enum { PROTOCOL_I2CT, PROTOCOL_OWIT, PROTOCOL_I2CW, PROTOCOL_I2CR, PROTOCOL_OWIW, PROTOCOL_OWIR, PROTOCOL_UNKNOWN } ProtocolType; static ProtocolType detect_protocol(char header1, char header2) { if (header1 == 'I' && header2 == 'W') return PROTOCOL_I2CW; if (header1 == 'I' && header2 == 'R') return PROTOCOL_I2CR; if (header1 == 'O' && header2 == 'W') return PROTOCOL_OWIW; if (header1 == 'O' && header2 == 'R') return PROTOCOL_OWIR; return PROTOCOL_UNKNOWN; } static void cmd_unknown(const unsigned char *d, unsigned int len) { (void)d; (void)len; OUT_PRINT(CMD_SRC_PC, "Unknown cmd\r\n"); delay(100000); } /* ¿©±â´Â ³× ÇÁ·ÎÁ§Æ® ±âÁ¸ ÇÔ¼öµé È£Ãâ */ static void process_cmd(ProtocolType protocol, uint8_t id, const unsigned char *data, unsigned int len) { switch (protocol) { case PROTOCOL_I2CT: I2C_T_Command_Mode_receiveData(data, (uint8_t)len, id); break; case PROTOCOL_OWIT: OWI_T_CommandMode(data, (uint8_t)len, id); break; case PROTOCOL_I2CW: I2C_Command_Mode_receiveData(data, (uint8_t)len, id); break; case PROTOCOL_I2CR: I2C_Command_Mode_Send((uint8_t)len, id); break; case PROTOCOL_OWIW: OWI_CommandMode(data, (uint8_t)len, id); break; case PROTOCOL_OWIR: OWI_ReadBytesAndPrint(len, id); break; default: cmd_unknown(data, len); break; } } static void process_cmd_by_prefix(PrefixMode pm, ProtocolType protocol, uint8_t id, const unsigned char *data, unsigned int len) { (void)pm; process_cmd(protocol, id, data, len); } /* ========================= * Main line processor * ========================= */ static void process_one_line(CmdSource src, const volatile uint8_t *rx_buf, uint16_t rx_len) { char line[UART_RX_BUF_SIZE]; uint8_t v_addr = 0; int is_v = 0; uint8_t a = 0; int i; int idx = 0; int pos = 2; ProtocolType proto; uint8_t id; unsigned int byte_len; uint8_t cmd[CMD_MAX]; unsigned int k = 0; char orig_line[UART_RX_BUF_SIZE]; int orig_len = 0; char msg[64]; s_prefix_mode = PREFIX_NONE; idx = build_line_from_rx(rx_buf, (int)rx_len, line, (int)sizeof(line)); if (idx <= 0) return; if (src == CMD_SRC_RS485) { if (!(line[0] == 'x' || line[0] == 'X')) return; // V/N/Err ÀÀ´ä µî ¹«½Ã } /* ========================= * 1) xNNv ó¸® (x-prefixº¸´Ù ¸ÕÀú) * ========================= */ is_v = parse_x_v_cmd(line, idx, &v_addr); if (is_v) { if (v_addr > 31) { OUT_PRINT(src, "Err:addr_range\r\n"); return; } /* º¸µå0(addr=0) + PC¿¡¼­ x00v => 00~31 ½ºÄµ */ if (g_fixed_addr == 0 && src == CMD_SRC_PC && v_addr == 0) { /* ÀÚ±â ÀÚ½Å(00) ÀÀ´ä */ send_v_response(CMD_SRC_PC, 0); /* 01~31 ¼øÂ÷ Á¶È¸ */ for (a = 1; a <= 31; a++) { scan_one_addr_rs485(a); } return; } /* ±× ¿Ü: ³» ÁÖ¼Ò¿Í ÀÏÄ¡ÇÒ ¶§¸¸ ÀÀ´ä */ if (v_addr == g_fixed_addr) { send_v_response(src, g_fixed_addr); } return; } /* ========================= * 1.5) xNNo ó¸® (OFF) ? ¼öÁ¤: º¸µå0ÀÌ ´Ù¸¥ ÁÖ¼Ò¸é RS485 Áß°è * ========================= */ { uint8_t off_addr = 0; if (parse_x_o_cmd(line, idx, &off_addr)) { if (off_addr > 31) { OUT_PRINT(src, "Err:addr_range\r\n"); return; } /* 1) ³» ÁÖ¼Ò¸é ·ÎÄà OFF */ if (off_addr == g_fixed_addr) { Cal_Init(); // ¡°Àüü OFF(±âº» »óÅÂ)¡± OUT_PRINT(src, "OFF\r\n"); send_end_response(); // GUI°¡ ¸ÖƼ¶óÀÎÀÌ¸é ÆíÇÔ return; } /* 2) º¸µå0(addr=0) + PC¿¡¼­ µé¾î¿Â x01o~ ´Â RS485·Î ºê¸´Áö */ if (g_fixed_addr == 0 && src == CMD_SRC_PC) { g_rs485_bridge_active = 1; g_rs485_bridge_done = 0; RS485_Bridge_ResetFifo(); rs485_rx_done = 0; rs485_rx_index = 0; rs485_rx_length = 0; R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1); /* ---- RS485·Î ¸í·É ¼Û½Å ---- */ { static char txbuf[UART_RX_BUF_SIZE + 4]; int n = idx; // line ±æÀÌ if (n > (int)sizeof(txbuf) - 3) n = (int)sizeof(txbuf) - 3; memcpy(txbuf, line, (size_t)n); txbuf[n++] = '\r'; txbuf[n++] = '\n'; txbuf[n] = '\0'; /* UART0 TX busy¸é Àá±ñ ´ë±â ÈÄ ¼Û½Å */ { unsigned long g = 0; while (g_uart0_tx_count != 0U) { if (g++ > 3000000UL) break; } } RS485_PRINT(txbuf); } /* ---- ÀÀ´ä µå·¹ÀÎ: µ¥ÀÌÅÍ 1¹øÀÌ¶óµµ ¿À°í 3ms idleÀ̸é Á¾·á ---- */ { uint32_t total_us = BRIDGE_TOTAL_WAIT_US; uint32_t idle_us = 0; uint16_t last_seq = g_rs485_bridge_seq; uint8_t got_any = 0; while (total_us >= 50U) { RS485_Bridge_DrainToPC(); delay_us(50); total_us -= 50U; if (g_rs485_bridge_done) break; // ¸é Á¾·á if (g_rs485_bridge_seq != last_seq) { last_seq = g_rs485_bridge_seq; got_any = 1; idle_us = 0; } else if (got_any) { idle_us += 50U; if (idle_us >= BRIDGE_IDLE_DONE_US) break; // 3ms idle } } RS485_Bridge_DrainToPC(); g_rs485_bridge_active = 0; if (total_us < 50U) { rs485_recover(); OUT_PRINT(CMD_SRC_PC, "Err:rs485_timeout\r\n"); sprintf(msg, "Err:rs485_timeout fef=%lu ovf=%lu pef=%lu\r\n", g_uart0_err_fef, g_uart0_err_ovf, g_uart0_err_pef); OUT_PRINT(CMD_SRC_PC, msg); } } } return; // ½½·¹À̺ê´Â mismatch¸é ±×³É ¹«½Ã } } /* RS485 Áß°è¿ë ¿øº» ÀúÀå */ orig_len = idx; memcpy(orig_line, line, (size_t)orig_len); orig_line[orig_len] = '\0'; /* ========================= * 2) x-prefix ó¸® * ========================= */ { uint8_t addr = 0; uint8_t ch = 0; char mode = 0; int payload_pos = 0; uint8_t hash_on = 0; uint8_t anaout_on = 0; uint8_t check_on = 1; uint32_t total_us = BRIDGE_TOTAL_WAIT_US; uint32_t idle_us = 0; uint16_t last_seq = g_rs485_bridge_seq; uint8_t got_any = 0; int r = parse_x_prefix(line, idx, &addr, &ch, &mode, &hash_on, &anaout_on, &check_on, &payload_pos); if (r == -1) { OUT_PRINT(src, "Err:X_prefix\r\n"); return; } if (r == 1) { if (addr > 31) { OUT_PRINT(src, "Err:addr_range\r\n"); return; } if (ch < 1 || ch > 20) { OUT_PRINT(src, "Err:ch_range\r\n"); return; } /* addr mismatch */ if (addr != g_fixed_addr) { /* º¸µå0(addr=0) + PC¿¡¼­¸¸ RS485 Áß°è */ if (g_fixed_addr == 0 && src == CMD_SRC_PC) { uint32_t total_us; uint32_t idle_us; uint16_t last_seq; uint8_t got_any; g_rs485_bridge_active = 1; g_rs485_bridge_done = 0; RS485_Bridge_ResetFifo(); rs485_rx_done = 0; rs485_rx_index = 0; rs485_rx_length = 0; R_UART0_Receive((uint8_t*)&rs485_rx_buffer[0], 1); /* ---- RS485·Î ¸í·É ¼Û½Å ---- */ { static char txbuf[UART_RX_BUF_SIZE + 4]; int n = orig_len; if (n > (int)sizeof(txbuf) - 3) n = (int)sizeof(txbuf) - 3; memcpy(txbuf, orig_line, (size_t)n); txbuf[n++] = '\r'; txbuf[n++] = '\n'; txbuf[n] = '\0'; /* UART0 TX busy¸é Àá±ñ ´ë±â ÈÄ ¼Û½Å */ { unsigned long g = 0; while (g_uart0_tx_count != 0U) { if (g++ > 3000000UL) break; } } RS485_PRINT(txbuf); } /* ---- ÀÀ´ä µå·¹ÀÎ ---- */ total_us = BRIDGE_TOTAL_WAIT_US; idle_us = 0; last_seq = g_rs485_bridge_seq; got_any = 0; while (total_us >= 50U) { RS485_Bridge_DrainToPC(); delay_us(50); total_us -= 50U; if (g_rs485_bridge_done) break; if (g_rs485_bridge_seq != last_seq) { last_seq = g_rs485_bridge_seq; got_any = 1; idle_us = 0; } else if (got_any) { idle_us += 50U; if (idle_us >= BRIDGE_IDLE_DONE_US) break; } } RS485_Bridge_DrainToPC(); g_rs485_bridge_active = 0; if (total_us < 50U) { rs485_recover(); OUT_PRINT(CMD_SRC_PC, "Err:rs485_timeout\r\n"); sprintf(msg, "Err:rs485_timeout fef=%lu ovf=%lu pef=%lu\r\n", g_uart0_err_fef, g_uart0_err_ovf, g_uart0_err_pef); OUT_PRINT(CMD_SRC_PC, msg); } } return; /* ½½·¹À̺ê´Â addr mismatch ¹«½Ã */ } /* addr == g_fixed_addr: ·ÎÄà ó¸®(ä³Î ¼±Åà µî) */ if (mode == 'C') { s_prefix_mode = PREFIX_CAL; Cal_Init(); Gate_SetByNum(ch, hash_on, anaout_on, check_on); GateCtrl_SelectChannel(ch); } else { s_prefix_mode = PREFIX_EOL; Eol_Init(); Gate_SetByNum(ch, hash_on, anaout_on, check_on); GateCtrl_SelectChannel(ch); } /* prefix¸¸ ¿Â °æ¿ì / payload ó¸® */ { int rem = idx - payload_pos; if (rem <= 0) { if (mode == 'E') { OUT_PRINT(src, "XE51\r\n"); return; } else { OUT_PRINT(src, "Err:CAL_need_payload\r\n"); return; } } if (mode == 'E') { OUT_PRINT(src, "Err:EOL_no_payload\r\n"); return; } for (i = 0; i < rem; i++) line[i] = line[payload_pos + i]; line[rem] = '\0'; idx = rem; pos = 2; } } } /* ========================= * 3) ÀÏ¹Ý Ä¿¸Çµå ÆÄ½Ì * ========================= */ if (idx < 7) { OUT_PRINT(src, "Err:short\r\n"); return; } { char h0 = (char)toupper((unsigned char)line[0]); char h1 = (char)toupper((unsigned char)line[1]); proto = detect_protocol(h0, h1); } if (proto == PROTOCOL_UNKNOWN) { OUT_PRINT(src, "Err:ID\r\n"); return; } if (line[pos] == 't' || line[pos] == 'T') { if (proto == PROTOCOL_OWIW) proto = PROTOCOL_OWIT; else if (proto == PROTOCOL_I2CW) proto = PROTOCOL_I2CT; pos++; } if (line[pos] == '_' || line[pos] == ':') pos++; if (pos + 1 >= idx) { OUT_PRINT(src, "Err:id_short\r\n"); return; } id = hex2byte(line[pos], line[pos + 1]); pos += 2; if (pos + 2 >= idx || !(line[pos] >= '0' && line[pos] <= '9') || !(line[pos+1] >= '0' && line[pos+1] <= '9') || !(line[pos+2] >= '0' && line[pos+2] <= '9')) { OUT_PRINT(src, "Err:len_dec\r\n"); return; } byte_len = (unsigned int)(100*(line[pos]-'0') + 10*(line[pos+1]-'0') + (line[pos+2]-'0')); pos += 3; if (byte_len > CMD_MAX) { OUT_PRINT(src, "Err:len_range\r\n"); return; } if (proto == PROTOCOL_OWIT || proto == PROTOCOL_I2CT || proto == PROTOCOL_OWIW || proto == PROTOCOL_I2CW) { if (byte_len == 0) { OUT_PRINT(src, "Err:payload0\r\n"); return; } if ((int)(pos + (int)byte_len*2) > idx) { OUT_PRINT(src, "Err:len_mismatch\r\n"); return; } for (k = 0; k < byte_len; k++) { cmd[k] = hex2byte(line[pos + 2*k], line[pos + 2*k + 1]); } pos += (int)byte_len * 2; if (pos != idx) { OUT_PRINT(src, "Err:len_trail\r\n"); return; } } else if (proto == PROTOCOL_OWIR || proto == PROTOCOL_I2CR) { if (byte_len == 0) { OUT_PRINT(src, "Err:read_len_nonzero\r\n"); return; } if (pos != idx) { OUT_PRINT(src, "Err:read_no_payload\r\n"); return; } } process_cmd_by_prefix(s_prefix_mode, proto, id, cmd, byte_len); } /* ========================= * Main loop handler * ========================= */ void handle_uart_command_line(void) { while (1) { if (g_rs485_need_recover) { /* 1) ºê¸´Áö °­Á¦ Á¾·á */ g_rs485_bridge_active = 0; g_rs485_bridge_done = 0; RS485_Bridge_ResetFifo(); // °°Àº ÆÄÀÏ ³» staticÀ̶ó È£Ãâ °¡´É /* 2) RS485 RX »óÅ Á¤¸® */ rs485_rx_done = 0; rs485_rx_index = 0; rs485_rx_length = 0; /* 3) UART0 stop/start + RX Àçarm */ rs485_recover(); g_rs485_need_recover = 0; } /* ºê¸´Áö ÁßÀ̸é RS485->PC °è¼Ó µå·¹ÀÎ */ if (g_rs485_bridge_active) { RS485_Bridge_DrainToPC(); } /* PC(UART1) */ if (uart_rx_done) { uart_rx_done = 0; process_one_line(CMD_SRC_PC, uart_rx_buffer, uart_rx_length); uart_rx_index = 0; uart_rx_length = 0; R_UART1_Receive((uint8_t *)&uart_rx_buffer[uart_rx_index], 1); } /* RS485(UART0) */ if (rs485_rx_done) { rs485_rx_done = 0; if (!g_rs485_bridge_active) { process_one_line(CMD_SRC_RS485, rs485_rx_buffer, rs485_rx_length); } rs485_rx_index = 0; rs485_rx_length = 0; R_UART0_Receive((uint8_t *)&rs485_rx_buffer[rs485_rx_index], 1); } else { } } } /* ========================= * Renesas entrypoints * ========================= */ void R_MAIN_UserInit(void); void main(void) { char b[64]; R_MAIN_UserInit(); R_UART0_Create(); /* UART0 : RS485 */ R_UART1_Create(); /* UART1 : PC */ R_IICA0_Create(); /* I2C */ R_UART0_Start(); R_UART1_Start(); sprintf(b, "BOOT addr=%u\r\n", g_fixed_addr); /* ? BOOT Ãâ·Âµµ ¾ÈÀü Ãâ·Â »ç¿ë */ UART1_SendString_Safe(b); RS485_PRINT(b); R_UART1_Receive((uint8_t *)&uart_rx_buffer[uart_rx_index], 1); R_UART0_Receive((uint8_t *)&rs485_rx_buffer[rs485_rx_index], 1); handle_uart_command_line(); while (1U) { ; } } void R_MAIN_UserInit(void) { /* Start user code. Do not edit comment generated here */ EI(); R_PORT_Create(); rs485_init(); DipSwitch_Init(); g_fixed_addr = DipSwitch_ReadAddr_0to31(); /* End user code. Do not edit comment generated here */ } /* End user code. Do not edit comment generated here */