📄 hw_ser800.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include "startup.h"#include <ppc/800cpu.h>#include <ppc/800cpm.h>// Receive buffer 8 * (16 bytes), send buffer 8 * (16 bytes)paddr32_t ptrTxBD[6];paddr32_t ptrRxBD[6];static voidparse_line(unsigned channel, const char *line, unsigned *baud, unsigned *clk, unsigned *div, paddr_t *base) {// base holds the 800 chanel no, like smc1, scc2, etc. if(*line != '.' && *line != '\0') { if(line[1] == 'm' || line[1] == 'M') { line += 3; dbg_device[channel].base = *line++ - '1'; } else if(line[1] == 'c' || line[1] == 'C') { line += 3; dbg_device[channel].base = *line++ - '1' + 2; } if(*line == '^') dbg_device[channel].shift = strtoul(line+1, (char **)&line, 0); } if(*line == '.') ++line; if(*line != '.' && *line != '\0') *baud = strtoul(line, (char **)&line, 0); if(*line == '.') ++line; if(*line != '.' && *line != '\0') *clk = strtoul(line, (char **)&line, 0); if(*line == '.') ++line; if(*line != '.' && *line != '\0') *div = strtoul(line, (char **)&line, 0); if(*line == '.') ++line; if(*line != '.' && *line != '\0') *base = strtopaddr(line, (char **)&line, 0);}static void sendCommand(uint16_t com, PPC8CPM_CH_NUM port) { static uint16_t chanelNo[6] = {PPC8CPM_CPCR_CH_SMC1DSP1, PPC8CPM_CPCR_CH_SMC2DSP2, PPC8CPM_CPCR_CH_SCC1, PPC8CPM_CPCR_CH_SCC2, PPC8CPM_CPCR_CH_SCC3, PPC8CPM_CPCR_CH_SCC4}; // wait for the command register available do { } while(PPC800_IMMR(CPCR, 16) & PPC8CPM_CPCR_FLG); // send command PPC800_IMMR(CPCR, 16) = com | chanelNo[port] | PPC8CPM_CPCR_FLG;}static void setBuffers (PPC8CPM_CH_NUM port, uint32_t base) { int i; paddr32_t addrDPRAM, ptr; static const paddr32_t addrBDT[6] = { PPC8CPM_DPRAM_BDT_SMC1, PPC8CPM_DPRAM_BDT_SMC2, PPC8CPM_DPRAM_BDT_SCC1, PPC8CPM_DPRAM_BDT_SCC2, PPC8CPM_DPRAM_BDT_SCC3, PPC8CPM_DPRAM_BDT_SCC4, }; static const paddr32_t addrDBuf[6] = { PPC8CPM_DPRAM_DBUF_SMC1, PPC8CPM_DPRAM_DBUF_SMC2, PPC8CPM_DPRAM_DBUF_SCC1, PPC8CPM_DPRAM_DBUF_SCC2, PPC8CPM_DPRAM_DBUF_SCC3, PPC8CPM_DPRAM_DBUF_SCC4 }; static const paddr32_t baseParaRAM[6] = { PPC8CPM_DPRAMPARA_SMC1_S, PPC8CPM_DPRAMPARA_SMC2_S, PPC8CPM_DPRAMPARA_SCC1_S, PPC8CPM_DPRAMPARA_SCC2_S, PPC8CPM_DPRAMPARA_SCC3_S, PPC8CPM_DPRAMPARA_SCC4_S }; paddr32_t dbuf, bdt; addrDPRAM = (paddr32_t) &PPC800_IMMR(DPRAM, 8); if(base < 0xffff) { bdt = base; dbuf = base + 0x100; } else { bdt = addrBDT[port]; dbuf = addrDBuf[port]; } // relocate receive buffer ptrRxBD[port] = ptr = addrDPRAM + bdt; out32(ptr, ptr + PPC8CPM_BD_SIZE - addrDPRAM); ptr += PPC8CPM_BD_SIZE; for(i=0; i<PPC8CPM_UART_DBNUM_D; i++) { out16(ptr, PPC8CPM_RXBD_E); ptr += 2; out16(ptr, 0); ptr += 2; out32(ptr, addrDPRAM+dbuf+PPC8CPM_UART_DBSIZE_D*i); ptr += 4; } ptr -= PPC8CPM_BD_SIZE; out16(ptr, PPC8CPM_RXBD_W|PPC8CPM_RXBD_E); out16(addrDPRAM+baseParaRAM[port]+PPC8CPM_PARARAM_SCCSMC_RBASE, ptrRxBD[port]-addrDPRAM + PPC8CPM_BD_SIZE); // start of real BDT is 8 bytes after // set receive buffer size out16(addrDPRAM+baseParaRAM[port]+PPC8CPM_PARARAM_SCCSMC_MRBLR, 1); // set MAX_IDL out16(addrDPRAM+baseParaRAM[port]+PPC8CPM_PARARAM_SCCUART_MAXIDL, 10); // Init Control Characters table for SCCs if(port > SMC2) out16(addrDPRAM+baseParaRAM[port]+PPC8CPM_PARARAM_SCCUART_CHARACTER1, PPC8CPM_PARARAM_SCCUART_CHAR_E); // relocate transmit buffer ptrTxBD[port] = ptr = addrDPRAM+bdt+PPC8CPM_BD_SIZE*(1+PPC8CPM_UART_DBNUM_D); out32(ptr, ptr + PPC8CPM_BD_SIZE - addrDPRAM); ptr += PPC8CPM_BD_SIZE; for(i=0; i<PPC8CPM_UART_DBNUM_D; i++) { out32(ptr, 0); ptr += 4; out32(ptr, addrDPRAM+dbuf+PPC8CPM_UART_DBSIZE_D*(PPC8CPM_UART_DBNUM_D+i)); ptr += 4; } ptr -= PPC8CPM_BD_SIZE; out16(ptr, PPC8CPM_TXBD_W); out16(addrDPRAM + baseParaRAM[port] + PPC8CPM_PARARAM_SCCSMC_TBASE, ptrTxBD[port]-addrDPRAM + PPC8CPM_BD_SIZE);// start of real BDT is 8 bytes after out16(addrDPRAM + baseParaRAM[port] + PPC8CPM_PARARAM_SCCSMC_RFCR, 0x1515);}voidinit_800cpm(unsigned channel, const char *init, const char *defaults) { unsigned baud; unsigned div; unsigned clk; unsigned cnt, value, brg; paddr_t base = 0xffffffff; PPC8CPM_CH_NUM port; parse_line(channel, defaults, &baud, &clk, &div, &base); parse_line(channel, init, &baud, &clk, &div, &base); port = dbg_device[channel].base; brg = dbg_device[channel].shift; // set baudrate cnt = (clk + ((baud * div) >> 1)) / (baud * div); // accurately if(cnt < PPC8CPM_BRG_MAXCNT) { value = PPC8CPM_BRG_EN | PPC8CPM_BRG_EXTC_BRGCLK | PPC8CPM_BRG_CD((--cnt)); } else { cnt = (cnt + 8) / 16; value = PPC8CPM_BRG_EN | PPC8CPM_BRG_EXTC_BRGCLK | PPC8CPM_BRG_CD((--cnt)) | PPC8CPM_BRG_DIV16; } switch(brg) { case 0: PPC800_IMMR(BRGC1, 32) = PPC8CPM_BRG_RST; PPC800_IMMR(BRGC1, 32) = value; PPC800_IMMR(BRGC1, 32) &= ~PPC8CPM_BRG_RST; break; case 1: PPC800_IMMR(BRGC2, 32) = PPC8CPM_BRG_RST; PPC800_IMMR(BRGC2, 32) = value; PPC800_IMMR(BRGC2, 32) &= ~PPC8CPM_BRG_RST; break; case 2: PPC800_IMMR(BRGC3, 32) = PPC8CPM_BRG_RST; PPC800_IMMR(BRGC3, 32) = value; PPC800_IMMR(BRGC3, 32) &= ~PPC8CPM_BRG_RST; break; case 3: PPC800_IMMR(BRGC4, 32) = PPC8CPM_BRG_RST; PPC800_IMMR(BRGC4, 32) = value; PPC800_IMMR(BRGC4, 32) &= ~PPC8CPM_BRG_RST; break; default: break; } switch(port) { case SMC1: // config GPIO PPC800_IMMR(PBPAR, 32) |= _ONEBIT32B(24) | _ONEBIT32B(25); // select mode and clock source PPC800_IMMR(SIMODE, 32) &= ~(PPC8CPM_SIMODE_SMC1 | PPC8CPM_SIMODE_SMC1CSM); PPC800_IMMR(SIMODE, 32) |= PPC8CPM_SIMODE_SMC1CS(brg); // program for line paras: 8bits, no parity, & disable send/receive PPC800_IMMR(SMCMR1, 16) = PPC8CPM_SMCMR_UART_SMUART | PPC8CPM_SMCMR_UART_CLEN(8,0,1); // disable int PPC800_IMMR(SMCM1, 16) = 0; break; case SMC2: // config GPIO if(PPC800_GET_PARTNUM != PPC800_PARTNUM_860_821) { PPC800_IMMR(PAPAR, 16) |= _ONEBIT16B(8) | _ONEBIT16B(9); } else { PPC800_IMMR(PBPAR, 32) |= _ONEBIT32B(20) | _ONEBIT32B(21); } // select mode and clock source PPC800_IMMR(SIMODE, 32) &= ~(PPC8CPM_SIMODE_SMC2 | PPC8CPM_SIMODE_SMC2CSM); PPC800_IMMR(SIMODE, 32) |= PPC8CPM_SIMODE_SMC2CS(brg); // program for line paras: 8bits, no parity, & disable send/receive PPC800_IMMR(SMCMR2, 16) = PPC8CPM_SMCMR_UART_SMUART | PPC8CPM_SMCMR_UART_CLEN(8,0,1); // disable int PPC800_IMMR(SMCM2, 16) = 0; break; case SCC1: // config GPIO PPC800_IMMR(PAPAR, 32) |= _ONEBIT32B(14) | _ONEBIT32B(15); // select mode and clock source PPC800_IMMR(SICR, 32) &= ~(PPC8CPM_SICR_SC1 | PPC8CPM_SICR_R1CSM | PPC8CPM_SICR_T1CSM); PPC800_IMMR(SICR, 32) |= PPC8CPM_SICR_R1CS(brg) | PPC8CPM_SICR_T1CS(brg); // config GSMR PPC800_IMMR(GSMR_H1, 32) = PPC8CPM_GSMR_H_RFW; PPC800_IMMR(GSMR_L1, 32) = PPC8CPM_GSMR_L_TDCR16 | PPC8CPM_GSMR_L_RDCR16 | PPC8CPM_GSMR_L_MODEUART; // program for line paras: 8bits, no parity PPC800_IMMR(PSMR1, 16) = PPC8CPM_SCCMR_UART_CL8; // disable int PPC800_IMMR(SCCM1, 16) = 0; break; case SCC2: // config GPIO PPC800_IMMR(PAPAR, 32) |= _ONEBIT32B(12) | _ONEBIT32B(13); // select mode and clock source PPC800_IMMR(SICR, 32) &= ~(PPC8CPM_SICR_SC2 | PPC8CPM_SICR_R2CSM | PPC8CPM_SICR_T2CSM); PPC800_IMMR(SICR, 32) |= PPC8CPM_SICR_R2CS(brg) | PPC8CPM_SICR_T2CS(brg); // config GSMR PPC800_IMMR(GSMR_H2, 32) = PPC8CPM_GSMR_H_RFW; PPC800_IMMR(GSMR_L2, 32) = PPC8CPM_GSMR_L_TDCR16 | PPC8CPM_GSMR_L_RDCR16 | PPC8CPM_GSMR_L_MODEUART; // program for line paras: 8bits, no parity PPC800_IMMR(PSMR2, 16) = PPC8CPM_SCCMR_UART_CL8; // disable int PPC800_IMMR(SCCM2, 16) = 0; break; case SCC3: // config GPIO PPC800_IMMR(PAPAR, 32) |= _ONEBIT32B(10) | _ONEBIT32B(11); // select mode and clock source PPC800_IMMR(SICR, 32) &= ~(PPC8CPM_SICR_SC3 | PPC8CPM_SICR_R3CSM | PPC8CPM_SICR_T3CSM); PPC800_IMMR(SICR, 32) |= PPC8CPM_SICR_R3CS(brg) | PPC8CPM_SICR_T3CS(brg); // config GSMR PPC800_IMMR(GSMR_H3, 32) = PPC8CPM_GSMR_H_RFW; PPC800_IMMR(GSMR_L3, 32) = PPC8CPM_GSMR_L_TDCR16 | PPC8CPM_GSMR_L_RDCR16 | PPC8CPM_GSMR_L_MODEUART; // program for line paras: 8bits, no parity PPC800_IMMR(PSMR3, 16) = PPC8CPM_SCCMR_UART_CL8; // disable int PPC800_IMMR(SCCM3, 16) = 0; break; case SCC4: // config GPIO PPC800_IMMR(PAPAR, 32) |= _ONEBIT32B(8) | _ONEBIT32B(9); // select mode and clock source PPC800_IMMR(SICR, 32) &= ~(PPC8CPM_SICR_SC4 | PPC8CPM_SICR_R4CSM | PPC8CPM_SICR_T4CSM); PPC800_IMMR(SICR, 32) |= PPC8CPM_SICR_R4CS(brg) | PPC8CPM_SICR_T4CS(brg); // config GSMR PPC800_IMMR(GSMR_H4, 32) = PPC8CPM_GSMR_H_RFW; PPC800_IMMR(GSMR_L4, 32) = PPC8CPM_GSMR_L_TDCR16 | PPC8CPM_GSMR_L_RDCR16 | PPC8CPM_GSMR_L_MODEUART; // program for line paras: 8bits, no parity PPC800_IMMR(PSMR4, 16) = PPC8CPM_SCCMR_UART_CL8; // disable int PPC800_IMMR(SCCM4, 16) = 0; break; default: break; } // set Rx TX buffers setBuffers(port, base); // reset para sendCommand(PPC8CPM_CPCR_INITRXTX, port); // enable send/receive switch(port) { case SMC1: PPC800_IMMR(SMCMR1, 16) |= (PPC8CPM_SMCMR_UART_TEN | PPC8CPM_SMCMR_UART_REN); break; case SMC2: PPC800_IMMR(SMCMR2, 16) |= (PPC8CPM_SMCMR_UART_TEN | PPC8CPM_SMCMR_UART_REN); break; case SCC1: PPC800_IMMR(GSMR_L1, 32) |= (PPC8CPM_GSMR_L_ENR | PPC8CPM_GSMR_L_ENT); break; case SCC2: PPC800_IMMR(GSMR_L2, 32) |= (PPC8CPM_GSMR_L_ENR | PPC8CPM_GSMR_L_ENT); break; case SCC3: PPC800_IMMR(GSMR_L3, 32) |= (PPC8CPM_GSMR_L_ENR | PPC8CPM_GSMR_L_ENT); break; case SCC4: PPC800_IMMR(GSMR_L4, 32) |= (PPC8CPM_GSMR_L_ENR | PPC8CPM_GSMR_L_ENT); break; default: break; }}voidput_800cpm(int c) { PPC8CPM_CH_NUM port = (PPC8CPM_CH_NUM) dbg_device[0].base; paddr32_t addrDPRAM = (paddr32_t) &PPC800_IMMR(DPRAM, 8); paddr32_t ptr = in32(ptrTxBD[port]) + addrDPRAM; // waiting for the transmit buffer ready do { } while(in16(ptr) & PPC8CPM_TXBD_R); // next available buffer if(in16(ptr) & PPC8CPM_TXBD_W) { out32(ptrTxBD[port], ptrTxBD[port] + PPC8CPM_BD_SIZE - addrDPRAM); } else { out32(ptrTxBD[port], ptr + PPC8CPM_BD_SIZE - addrDPRAM); } // Write a char to the buffer out8(in32(ptr+PPC8CPM_BD_POINTER), c); out16(ptr+PPC8CPM_BD_COUNT, 1); out16(ptr, in16(ptr) | PPC8CPM_TXBD_R);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -