delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2009/05/14/08:45:44

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: =?ISO-2022-JP?B?GyRCPi44UUBnGyhC?= <foxapple AT gmail DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: An interrupt drived uart program dead
Date: Thu, 14 May 2009 05:34:46 -0700 (PDT)
Organization: http://groups.google.com
Lines: 178
Message-ID: <dcff139d-32b8-4f22-ab4a-6f7e78f81324@c18g2000prh.googlegroups.com>
NNTP-Posting-Host: 58.38.3.10
Mime-Version: 1.0
X-Trace: posting.google.com 1242304487 31211 127.0.0.1 (14 May 2009 12:34:47 GMT)
X-Complaints-To: groups-abuse AT google DOT com
NNTP-Posting-Date: Thu, 14 May 2009 12:34:47 +0000 (UTC)
Complaints-To: groups-abuse AT google DOT com
Injection-Info: c18g2000prh.googlegroups.com; posting-host=58.38.3.10;
posting-account=qc6pEAoAAACyFixjIDHUvf8HsKSt31ce
User-Agent: G2/1.0
X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR
1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022;
InfoPath.2; aff-kingsoft-ciba; TheWorld),gzip(gfe),gzip(gfe)
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

I wrote a program under djgpp to drive PC UART. the program is
interrupt-drived. When run the program, the data has sent, but then
the PC halt. I can't find any bug in the program. So ask for help.
below is the program code.

#include <dos.h>
#include <stdio.h>
#include <stddef.h>
#include <pc.h>
#include <dpmi.h>
#include <go32.h>

#define LOCK_VARIABLE(x)    _go32_dpmi_lock_data((void *)&x,(long)
sizeof(x));
#define LOCK_FUNCTION(x)    _go32_dpmi_lock_code(x,(long)sizeof(x));

typedef unsigned char byte;
typedef unsigned short uint16_t;

enum RegisterOffset
{
   OFFSET_RBR = 0,
   OFFSET_THR = 0,
   OFFSET_IER = 1,
   OFFSET_IIR = 2,
   OFFSET_FCR = 2,
   OFFSET_LCR = 3,
   OFFSET_MCR = 4,
   OFFSET_LSR = 5,
   OFFSET_MSR = 6,
   OFFSET_SCR = 7,
   OFFSET_DLL = 0,
   OFFSET_DLM = 1
};

enum RegisterConst
{
   LCR_BREAKOFF = 0, LCR_BREAKON = 0x40, LCR_DLABOFF = 0, LCR_DLABON =
0x80,

   FCR_CLEARENB = 0x1, FCR_RCLEAR = 0x2, FCR_XCLEAR = 0x4, FCR_MODE =
0x8,
   FCR_LEVEL1 = 0x0, FCR_LEVEL4 = 0x40, FCR_LEVEL8 = 0x80, FCR_LEVEL13
= 0xc0,

   MCR_ACTDTR = 0x1, MCR_ACTRTS = 0x2, MCR_OUT1 = 0x4, MCR_OUT2 = 0x8,
MCR_LOOPBACK = 0x10,

   IER_ERBFI = 0x1, IER_ETBEI = 0x2, IER_ELSI = 0x4, IER_EDSSI = 0x8,
IER_DISALL = 0, IER_ENBALL = 0x0f,

   LSR_DR = 0x1, LSR_OE = 0x2, LSR_PE = 0x4, LSR_FE=0x8, LSR_BI=0x10,
LSR_THRE=0x20, LSR_TEMT=0x40, LSR_TIMEOUT=0x80,

   MSR_DCTS=0x1, MSR_DDSR=0x2, MSR_TERI=0x4, MSR_DDCD=0x8,
MSR_CTS=0x10, MSR_DSR=0x20, MSR_RI=0x40, MSR_DCD=0x80,

   IIR_NOINT = 0x1, IIR_IMSC = 0x0, IIR_ITBE = 0x2, IIR_IRBF = 0x4,
IIR_ILS = 0x6, IIR_TIMEOUT = 0x8, IIR_IMASK = 0x0e
};

const unsigned int baseAddress = 0x3f8;
const byte commIrq = 0x04;
const byte commIntr = 0x0c;
bool txIdle = true;

_go32_dpmi_seginfo OldISR, NewISR;
byte oldIMR;

void commISR();

int initComm()
{
   const byte wordSize = 0x03;      // 8-bit
   const byte stopBits = 0x00;      // 1-stop bit
   const byte parity = 0x00;        // none

   byte lcrSet = LCR_DLABON;
   outportb(baseAddress + OFFSET_LCR, lcrSet);
   uint16_t baudWord = 1843200 / (115200 * 16);
   outportb(baseAddress + OFFSET_DLL, baudWord & 0xff);        // set
low byte of baud rate word.
   outportb(baseAddress + OFFSET_DLM, (baudWord >> 8) & 0xff); // set
high byte of baud rate word.

   lcrSet = wordSize + stopBits + parity;
   outportb(baseAddress + OFFSET_LCR, lcrSet);                 // set
LCR to specified config.

   // disable FIFO
   outportb(baseAddress + OFFSET_FCR, 0);
   outportb(baseAddress + OFFSET_SCR, 0);

   outportb(baseAddress + OFFSET_MCR, MCR_ACTDTR+MCR_ACTRTS
+MCR_OUT1+MCR_OUT2);       // enable COM output gate.

   // clear the status.
   inportb(baseAddress + OFFSET_RBR);
   inportb(baseAddress + OFFSET_LSR);
   inportb(baseAddress + OFFSET_MSR);
   inportb(baseAddress + OFFSET_IIR);

   txIdle = true;

   _go32_dpmi_get_protected_mode_interrupt_vector(commIntr, &OldISR);
   NewISR.pm_offset = (int)commISR;
   NewISR.pm_selector = _go32_my_cs();
   _go32_dpmi_allocate_iret_wrapper(&NewISR);
   _go32_dpmi_set_protected_mode_interrupt_vector(commIntr, &NewISR);

   oldIMR = inportb(0x21);
   byte newIMR = oldIMR & (~(0x01 << 4));
   outportb(0x21, newIMR);
}

void restoreComm()
{
   _go32_dpmi_set_protected_mode_interrupt_vector(commIntr, &OldISR);
   _go32_dpmi_free_iret_wrapper(&NewISR);
   outportb(0x21, oldIMR);
}

#define QUEUE_CAPABILITY 16
byte writeQueue[QUEUE_CAPABILITY];
uint16_t queueHead = 0, queueTail = 0;
uint16_t queueSize = 0;

int asyWriteComm()
{
   for(int count = 0; count < QUEUE_CAPABILITY; count ++)
   {
      writeQueue[queueTail] = 'a' + count;
      queueTail = (queueTail + 1) % QUEUE_CAPABILITY;
      queueSize ++;
   }

   byte data = writeQueue[queueHead];
   queueHead = (queueHead + 1) % QUEUE_CAPABILITY;
   queueSize --;
   outportb(baseAddress + OFFSET_THR, data);
   txIdle = false;
   do {
   } while(queueSize != 0);
}

void commISR()
{
   byte iir = inportb(baseAddress + OFFSET_IIR);
   if ((iir & 0x02) != 0)
   {
      byte lsr;
      do {
         if (queueSize > 0)
         {
            byte data = writeQueue[queueHead];
            queueHead = (queueHead + 1) % QUEUE_CAPABILITY;
            queueSize --;
            outportb(baseAddress + OFFSET_THR, data);
            txIdle = false;
         }
         else
         {
            txIdle = true;
         }
         lsr = inportb(baseAddress + OFFSET_LSR);
      } while((lsr & (LSR_THRE | LSR_TEMT)) != 0);
   }
   outportb(0x20, 0x20);
}

int main()
{
   initComm();
   asyWriteComm();
   restoreComm();

   return 0;
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019