⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hw_ser8260.c

📁 qnx powerpc MPC8245的 BSP源文件
💻 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/8260cpu.h>#include <ppc/8260cpm.h>// Receive buffer 8 * (16 bytes), send buffer 8 * (16 bytes)#undef  PPC8260_IMMR#define PPC8260_IMMR(reg,size)  (*(volatile uint##size##_t *) (pv_immr_base_addr+PPC8260_IMMR_OFF_##reg))static uintptr_t pv_immr_base_addr;paddr32_t	ptrTxBD[6];paddr32_t	ptrRxBD[6];extern uint32_t ppc8260_brgclk;static voidparse_line(unsigned channel, const char *line, unsigned *baud,	unsigned *clk, unsigned *div, paddr_t *base) {// base holds the 8260 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 sendCommand8260(uint32_t com,  PPC8260CPM_CH_NUM port) {	static uint32_t chanelID[6] = {PPC8260CPM_CPCR_PAGE_SMC1 | PPC8260CPM_CPCR_SBC_SMC1,							PPC8260CPM_CPCR_PAGE_SMC2 | PPC8260CPM_CPCR_SBC_SMC2,							PPC8260CPM_CPCR_PAGE_SCC1 | PPC8260CPM_CPCR_SBC_SCC1,							PPC8260CPM_CPCR_PAGE_SCC2 | PPC8260CPM_CPCR_SBC_SCC2,							PPC8260CPM_CPCR_PAGE_SCC3 | PPC8260CPM_CPCR_SBC_SCC3,							PPC8260CPM_CPCR_PAGE_SCC4 | PPC8260CPM_CPCR_SBC_SCC4,							};	// wait for the command register available	do {	} while(PPC8260_IMMR(CPCR, 32) & PPC8260CPM_CPCR_FLG);	// send command	PPC8260_IMMR(CPCR, 32) = com | chanelID[port] | PPC8260CPM_CPCR_FLG;}static void setBuffers8260 (PPC8260CPM_CH_NUM port, uint32_t base) {	int i;	paddr32_t addrDPRAM, ptr;	uintptr_t v2p_off = pv_immr_base_addr - (immr_paddr + cpm_offset);	static const paddr32_t addrBDT[6] = {		PPC8260CPM_DPRAM_BDT_SMC1, 		PPC8260CPM_DPRAM_BDT_SMC2, 		PPC8260CPM_DPRAM_BDT_SCC1, 		PPC8260CPM_DPRAM_BDT_SCC2, 		PPC8260CPM_DPRAM_BDT_SCC3, 		PPC8260CPM_DPRAM_BDT_SCC4,	};	static const paddr32_t addrDBuf[6] = {		PPC8260CPM_DPRAM_DBUF_SMC1,		PPC8260CPM_DPRAM_DBUF_SMC2,		PPC8260CPM_DPRAM_DBUF_SCC1,		PPC8260CPM_DPRAM_DBUF_SCC2,		PPC8260CPM_DPRAM_DBUF_SCC3,		PPC8260CPM_DPRAM_DBUF_SCC4	};	static const paddr32_t	baseParaRAM[6] = {		PPC8260CPM_DPRAM_PARA_SMC1,		PPC8260CPM_DPRAM_PARA_SMC2,		PPC8260CPM_DPRAMPARA_SCC1,		PPC8260CPM_DPRAMPARA_SCC2,		PPC8260CPM_DPRAMPARA_SCC3,		PPC8260CPM_DPRAMPARA_SCC4	};	paddr32_t dbuf, bdt;	addrDPRAM = (paddr32_t) &PPC8260_IMMR(DPRAM1, 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 + PPC8260CPM_BD_SIZE - addrDPRAM);	ptr += PPC8260CPM_BD_SIZE;		for(i=0; i<PPC8260CPM_UART_DBNUM_D; i++) {		out16(ptr, PPC8260CPM_UART_RXBD_E);		ptr += 2;		out16(ptr, 0);		ptr += 2;		out32(ptr, addrDPRAM-v2p_off+dbuf+PPC8260CPM_UART_DBSIZE_D*i);		ptr += 4;			}	ptr -= PPC8260CPM_BD_SIZE;	out16(ptr, PPC8260CPM_UART_RXBD_W|PPC8260CPM_UART_RXBD_E);	out16(addrDPRAM+baseParaRAM[port]+PPC8260CPM_PARARAM_SCCSMC_RBASE,		ptrRxBD[port]-addrDPRAM + PPC8260CPM_BD_SIZE); // start of real BDT is 8 bytes after	// set receive buffer size	out16(addrDPRAM+baseParaRAM[port]+PPC8260CPM_PARARAM_SCCSMC_MRBLR, 1);	if(port > PPC8260_SMC2) {		// Init Control Characters table for SCCs		out16(addrDPRAM+baseParaRAM[port]+PPC8260CPM_PARARAM_SCCUART_CHAR1, PPC8260CPM_PARARAM_SCCUART_CHAR_E);		// set MAX_IDL		out16(addrDPRAM+baseParaRAM[port]+PPC8260CPM_PARARAM_SCCUART_MAXIDL, 10);	}		// relocate transmit buffer	ptrTxBD[port] = ptr = addrDPRAM+bdt+PPC8260CPM_BD_SIZE*(1+PPC8260CPM_UART_DBNUM_D);	out32(ptr, ptr + PPC8260CPM_BD_SIZE - addrDPRAM);	ptr += PPC8260CPM_BD_SIZE;		for(i=0; i<PPC8260CPM_UART_DBNUM_D; i++) {		out32(ptr, 0);		ptr += 4;		out32(ptr, addrDPRAM-v2p_off+dbuf+PPC8260CPM_UART_DBSIZE_D*(PPC8260CPM_UART_DBNUM_D+i));		ptr += 4;			}	ptr -= PPC8260CPM_BD_SIZE;	out16(ptr, PPC8260CPM_UART_TXBD_W);	out16(addrDPRAM + baseParaRAM[port] + PPC8260CPM_PARARAM_SCCSMC_TBASE,		ptrTxBD[port]-addrDPRAM + PPC8260CPM_BD_SIZE);// start of real BDT is 8 bytes after	out16(addrDPRAM + baseParaRAM[port] + PPC8260CPM_PARARAM_SCCSMC_RFCR, 0x1010);}voidinit_8260cpm(unsigned channel, const char *init, const char *defaults) {	unsigned baud;	unsigned div;	unsigned clk;	unsigned cnt, value, brg;	paddr_t base = 0xffffffff;	PPC8260CPM_CH_NUM port;	pv_immr_base_addr = startup_io_map(0x14000, immr_paddr + cpm_offset);	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;	/*	 * For PQ2FADS board and 8266ADS-PCI board, the BRG clock will	 * change depending which MODCK switches are set. So, setting	 * the BRG clock to a fixed value in startup won't work in all	 * cases. If 0 is specified in the debug_devices struct as the	 * clock frequency, then determine the correct BRG clock by	 * reading the PLL multiplication factor.	 */	if (clk == 0)		clk = ppc8260_brgclk;	switch(port) {	case PPC8260_SMC1:		// config GPIO		PPC8260_IMMR(PSORD, 32) &= ~(_ONEBIT32B(8) | _ONEBIT32B(9));		PPC8260_IMMR(PDIRD, 32) |= _ONEBIT32B(9);		PPC8260_IMMR(PDIRD, 32) &= ~_ONEBIT32B(8);		PPC8260_IMMR(PPARD, 32) |= _ONEBIT32B(9) | _ONEBIT32B(8);		// select mode and clock source		PPC8260_IMMR(CMXSMR, 8) &= ~(PPC8260CPM_CMXSMR_SMC1);		if(brg == 6) {			PPC8260_IMMR(CMXSMR, 8) |= PPC8260CPM_CMXSMR_SMC1CS_BRG7;		} else { 			PPC8260_IMMR(CMXSMR, 8) |= PPC8260CPM_CMXSMR_SMC1CS_BRG1;			brg = 0;		}		// program for line paras: 8bits, no parity, & disable send/receive		PPC8260_IMMR(SMCMR1, 16) = PPC8260CPM_SMCMR_UART_SMUART	| PPC8260CPM_SMCMR_UART_CLEN(8,0,1);		// disable int		PPC8260_IMMR(SMCM1, 8) = 0;		// init parameter base ptr		out16((paddr32_t)&PPC8260_IMMR(DPRAM1, 8) + PPC8260CPM_DPRAMPARA_SMC1_BASE, PPC8260CPM_DPRAM_PARA_SMC1);		break;	case PPC8260_SMC2:		// config GPIO		PPC8260_IMMR(PSORA, 32) &= ~(_ONEBIT32B(8) | _ONEBIT32B(9));		PPC8260_IMMR(PDIRA, 32) |= _ONEBIT32B(9);		PPC8260_IMMR(PDIRA, 32) &= ~_ONEBIT32B(8);		PPC8260_IMMR(PPARA, 32) |= _ONEBIT32B(8) | _ONEBIT32B(9);		// select mode and clock source		PPC8260_IMMR(CMXSMR, 8) &= ~(PPC8260CPM_CMXSMR_SMC2);		if(brg == 7) {			PPC8260_IMMR(CMXSMR, 8) |= PPC8260CPM_CMXSMR_SMC2CS_BRG8;		} else {			PPC8260_IMMR(CMXSMR, 8) |= PPC8260CPM_CMXSMR_SMC2CS_BRG2;			brg = 1;		}		// program for line paras: 8bits, no parity, & disable send/receive		PPC8260_IMMR(SMCMR2, 16) = PPC8260CPM_SMCMR_UART_SMUART	| PPC8260CPM_SMCMR_UART_CLEN(8,0,1);		// disable int		PPC8260_IMMR(SMCM2, 8) = 0;		// init parameter base ptr		out16((paddr32_t)&PPC8260_IMMR(DPRAM1, 8) + PPC8260CPM_DPRAMPARA_SMC2_BASE, PPC8260CPM_DPRAM_PARA_SMC2);		break;	case PPC8260_SCC1:		// config GPIO		PPC8260_IMMR(PSORD, 32) &= ~_ONEBIT32B(31);		PPC8260_IMMR(PSORD, 32) |= _ONEBIT32B(30);		PPC8260_IMMR(PDIRD, 32) |= _ONEBIT32B(30);		PPC8260_IMMR(PDIRD, 32) &= ~_ONEBIT32B(31);		PPC8260_IMMR(PPARD, 32) |= _ONEBIT32B(30) | _ONEBIT32B(31);		// select mode and clock source		PPC8260_IMMR(CMXSCR, 32) &= ~(PPC8260CPM_CMXSCR_GR1 |  PPC8260CPM_CMXSCR_SC1 | PPC8260CPM_CMXSCR_RS1CS_M | PPC8260CPM_CMXSCR_TS1CS_M);		if(brg <= 3) {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS1CS(brg) | PPC8260CPM_CMXSCR_TS1CS(brg);		} else {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS1CS_BRG1 | PPC8260CPM_CMXSCR_TS1CS_BRG1;			brg = 0;		}		// config GSMR		PPC8260_IMMR(GSMR_H1, 32) = PPC8260CPM_GSMR_H_RFW;		PPC8260_IMMR(GSMR_L1, 32) = PPC8260CPM_GSMR_L_TDCR16 | PPC8260CPM_GSMR_L_RDCR16 | PPC8260CPM_GSMR_L_MODEUART;		// program for line paras: 8bits, no parity 		PPC8260_IMMR(PSMR1, 16) =	PPC8260CPM_SCCMR_UART_CL8;		// disable int		PPC8260_IMMR(SCCM1, 16) = 0;		break;	case PPC8260_SCC2:		// config GPIO		PPC8260_IMMR(PSORD, 32) &= ~(_ONEBIT32B(27) | _ONEBIT32B(28));		PPC8260_IMMR(PDIRD, 32) |= _ONEBIT32B(27);		PPC8260_IMMR(PDIRD, 32) &= ~_ONEBIT32B(28);		PPC8260_IMMR(PPARD, 32) |= _ONEBIT32B(27) | _ONEBIT32B(28);		// select mode and clock source		PPC8260_IMMR(CMXSCR, 32) &= ~(PPC8260CPM_CMXSCR_GR2 |  PPC8260CPM_CMXSCR_SC2 | PPC8260CPM_CMXSCR_RS2CS_M | PPC8260CPM_CMXSCR_TS2CS_M);		if(brg <= 3) {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS2CS(brg) | PPC8260CPM_CMXSCR_TS2CS(brg);		} else {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS2CS_BRG1 | PPC8260CPM_CMXSCR_TS2CS_BRG1;			brg = 0;		}		// config GSMR		PPC8260_IMMR(GSMR_H2, 32) = PPC8260CPM_GSMR_H_RFW;		PPC8260_IMMR(GSMR_L2, 32) = PPC8260CPM_GSMR_L_TDCR16 | PPC8260CPM_GSMR_L_RDCR16 | PPC8260CPM_GSMR_L_MODEUART;		// program for line paras: 8bits, no parity 		PPC8260_IMMR(PSMR2, 16) =	PPC8260CPM_SCCMR_UART_CL8;		// disable int		PPC8260_IMMR(SCCM2, 16) = 0;		break;	case PPC8260_SCC3:		// config GPIO		PPC8260_IMMR(PSORD, 32) &= ~(_ONEBIT32B(24) | _ONEBIT32B(25));		PPC8260_IMMR(PDIRD, 32) |= _ONEBIT32B(24);		PPC8260_IMMR(PDIRD, 32) &= ~_ONEBIT32B(25);		PPC8260_IMMR(PPARD, 32) |= _ONEBIT32B(24) | _ONEBIT32B(25);		// select mode and clock source		PPC8260_IMMR(CMXSCR, 32) &= ~(PPC8260CPM_CMXSCR_GR3 |  PPC8260CPM_CMXSCR_SC3 | PPC8260CPM_CMXSCR_RS3CS_M | PPC8260CPM_CMXSCR_TS3CS_M);		if(brg <= 3) {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS3CS(brg) | PPC8260CPM_CMXSCR_TS3CS(brg);		} else {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS3CS_BRG1 | PPC8260CPM_CMXSCR_TS3CS_BRG1;			brg = 0;		}		// config GSMR		PPC8260_IMMR(GSMR_H3, 32) = PPC8260CPM_GSMR_H_RFW;		PPC8260_IMMR(GSMR_L3, 32) = PPC8260CPM_GSMR_L_TDCR16 | PPC8260CPM_GSMR_L_RDCR16 | PPC8260CPM_GSMR_L_MODEUART;		// program for line paras: 8bits, no parity 		PPC8260_IMMR(PSMR3, 16) =	PPC8260CPM_SCCMR_UART_CL8;		// disable int		PPC8260_IMMR(SCCM3, 16) = 0;		break;	case PPC8260_SCC4:		// config GPIO		PPC8260_IMMR(PSORD, 32) &= ~(_ONEBIT32B(21) | _ONEBIT32B(22));		PPC8260_IMMR(PDIRD, 32) |= _ONEBIT32B(21);		PPC8260_IMMR(PDIRD, 32) &= ~_ONEBIT32B(22);		PPC8260_IMMR(PPARD, 32) |= _ONEBIT32B(21) | _ONEBIT32B(22);		// select mode and clock source		PPC8260_IMMR(CMXSCR, 32) &= ~(PPC8260CPM_CMXSCR_GR4 |  PPC8260CPM_CMXSCR_SC4 | PPC8260CPM_CMXSCR_RS4CS_M | PPC8260CPM_CMXSCR_TS4CS_M);		if(brg <= 3) {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS4CS(brg) | PPC8260CPM_CMXSCR_TS4CS(brg);		} else {			PPC8260_IMMR(CMXSCR, 32) |= PPC8260CPM_CMXSCR_RS4CS_BRG1 | PPC8260CPM_CMXSCR_TS4CS_BRG1;			brg = 0;		}		// config GSMR		PPC8260_IMMR(GSMR_H4, 32) = PPC8260CPM_GSMR_H_RFW;		PPC8260_IMMR(GSMR_L4, 32) = PPC8260CPM_GSMR_L_TDCR16 | PPC8260CPM_GSMR_L_RDCR16 | PPC8260CPM_GSMR_L_MODEUART;		// program for line paras: 8bits, no parity 		PPC8260_IMMR(PSMR4, 16) =	PPC8260CPM_SCCMR_UART_CL8;		// disable int		PPC8260_IMMR(SCCM4, 16) = 0;		break;	default:		break;	}	// set baudrate	cnt = (clk + ((baud * div) >> 1)) / (baud * div); // accurately	if(cnt < PPC8260CPM_BRG_MAXCNT) {		value = PPC8260CPM_BRG_EN | PPC8260CPM_BRG_EXTC(0)			| PPC8260CPM_BRG_CD((--cnt));	} else {		cnt = (cnt + 8) / 16;		value = PPC8260CPM_BRG_EN | PPC8260CPM_BRG_EXTC(0)			| PPC8260CPM_BRG_CD((--cnt)) | PPC8260CPM_BRG_DIV16;	}	switch(brg) {	case 0:		PPC8260_IMMR(BRGC1, 32) = value;		break;	case 1:		PPC8260_IMMR(BRGC2, 32) = value;		break;	case 2:		PPC8260_IMMR(BRGC3, 32) = value;		break;	case 3:		PPC8260_IMMR(BRGC4, 32) = value;		break;	case 4:		PPC8260_IMMR(BRGC5, 32) = value;		break;	case 5:		PPC8260_IMMR(BRGC6, 32) = value;		break;	case 6:		PPC8260_IMMR(BRGC7, 32) = value;		break;	case 7:		PPC8260_IMMR(BRGC8, 32) = value;		break;	default:		break;	}	// set Rx TX buffers	setBuffers8260(port, base);	// reset para	sendCommand8260(PPC8260CPM_CPCR_INITRXTX, port);	// enable send/receive	switch(port) {	case PPC8260_SMC1:		PPC8260_IMMR(SMCMR1, 16) |= (PPC8260CPM_SMCMR_UART_TEN | PPC8260CPM_SMCMR_UART_REN);		break;	case PPC8260_SMC2:		PPC8260_IMMR(SMCMR2, 16) |= (PPC8260CPM_SMCMR_UART_TEN | PPC8260CPM_SMCMR_UART_REN);		break;	case PPC8260_SCC1:		PPC8260_IMMR(GSMR_L1, 32) |= (PPC8260CPM_GSMR_L_ENR	| PPC8260CPM_GSMR_L_ENT);		break;	case PPC8260_SCC2:		PPC8260_IMMR(GSMR_L2, 32) |= (PPC8260CPM_GSMR_L_ENR	| PPC8260CPM_GSMR_L_ENT);		break;	case PPC8260_SCC3:		PPC8260_IMMR(GSMR_L3, 32) |= (PPC8260CPM_GSMR_L_ENR	| PPC8260CPM_GSMR_L_ENT);		break;	case PPC8260_SCC4:		PPC8260_IMMR(GSMR_L4, 32) |= (PPC8260CPM_GSMR_L_ENR	| PPC8260CPM_GSMR_L_ENT);		break;	default:		break;	}	startup_io_unmap(pv_immr_base_addr);}voidput_8260cpm(int c) {	PPC8260CPM_CH_NUM	port;	paddr32_t			addrDPRAM;	paddr32_t			ptr;	uintptr_t 			v2p_off;	pv_immr_base_addr = startup_io_map(0x14000, immr_paddr + cpm_offset);	v2p_off = pv_immr_base_addr - (immr_paddr + cpm_offset);	port = (PPC8260CPM_CH_NUM) dbg_device[0].base;	addrDPRAM = (paddr32_t)&PPC8260_IMMR(DPRAM1, 8);	ptr = in32(ptrTxBD[port]) + addrDPRAM;	// waiting for the transmit buffer ready	do {	} while(in16(ptr) & PPC8260CPM_UART_TXBD_R);	// next available buffer	if(in16(ptr) & PPC8260CPM_UART_TXBD_W) {		out32(ptrTxBD[port], ptrTxBD[port] + PPC8260CPM_BD_SIZE - addrDPRAM);	} else {		out32(ptrTxBD[port], ptr + PPC8260CPM_BD_SIZE - addrDPRAM);	}	// Write a char to the buffer	out8(in32(ptr+PPC8260CPM_BD_POINTER)+v2p_off, c);	out16(ptr+PPC8260CPM_BD_COUNT, 1);	out16(ptr, in16(ptr) | PPC8260CPM_UART_TXBD_R);	startup_io_unmap(pv_immr_base_addr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -