OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [sim-plugins/] [miniUART/] [miniUART.c] - Blame information for rev 27

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 jlechner
/* SCARTS miniUART extension module code for the GNU simulator.
2
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3
   Free Software Foundation, Inc.
4
   Contributed by Martin Walter <mwalter@opencores.org>
5
 
6
   This file is part of the GNU simulators.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
 
22
#define _XOPEN_SOURCE
23
#include <errno.h>
24
#include <fcntl.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <strings.h>
29
#include <termios.h>
30
#include <unistd.h>
31
#include "miniUART.h"
32
 
33
/* Macros for machine type. */
34
#if defined __SCARTS_16__
35
  #define SCARTS_ADDR_CTYPE  uint16_t
36
#elif defined __SCARTS_32__
37
  #define SCARTS_ADDR_CTYPE  uint32_t
38
#else
39
  #error "Unsupported target machine type"
40
#endif
41
 
42
/* Macros for the assigned action (ASA) in the CMD register. */
43
#define UART_CMD_ASA_BITMASK    0x38
44
#define UART_CMD_ASA_TxStart    (0x3 << 3)
45
#define UART_CMD_ASA_RxEnable   (0x4 << 3)
46
#define UART_CMD_ASA_RxDisable  (0x5 << 3)
47
 
48
/* Macros for the event selector (ES) in the CMD register. */
49
#define UART_CMD_ES_MASK        0x06
50
#define UART_CMD_ES_NoEvent     0x00
51
#define UART_CMD_ES_StartBitRec (0x1 << 1)
52
#define UART_CMD_ES_RxComplete  (0x2 << 1)
53
#define UART_CMD_ES_TxStarted   (0x3 << 1)
54
 
55
/* Macros for bit manipulations. */
56
#define read_bit(regfile, bitpos) (((regfile) >> (bitpos)) & 1)
57
#define write_bit(regfile, bitpos, value) (void)((value) ? ((regfile) |= (1 << (bitpos))) : ((regfile) &= ~(1 << (bitpos))))
58
 
59
static miniuart_mem_t mem;
60
static int fdm          = -1; /* File handle of pseudo TTY master. */
61
static int rxEnabled    =  0; /* Does the simulated serial port accept any incoming data? */
62
static int txCnt        =  1; /* Simulates time the data transmission takes (cpu cycles). */
63
static int txMsgChanged =  0; /* Did MSG register contents change since last transmission? */
64
 
65
static void set_event_flag (void);
66
static int  stty_raw       (int fd);
67
 
68
static void
69
set_event_flag (void)
70
{
71
  /* Set the MINI_UART_STATUS_C_EF flag. */
72
  write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_EF, 1);
73
 
74
  /* Check if the MINI_UART_CMD_EI flag is set. */
75
  if (read_bit (mem.regfile.CMD, MINI_UART_CMD_EI))
76
    /* Trigger an interrupt. */
77
    write_bit (mem.regfile.STATUS, MINI_UART_STATUS_INT, 1);
78
}
79
 
80
static int
81
stty_raw (int fd)
82
{
83
  struct termios tty_state;
84
 
85
  bzero (&tty_state, sizeof (tty_state));
86
  tty_state.c_cflag = B38400 | CS8 | CLOCAL | CREAD;
87
  tty_state.c_iflag = IGNPAR;
88
  tty_state.c_oflag = 0;
89
 
90
  /* Configure for blocking read until 1 chars received. */
91
  tty_state.c_cc[VMIN]  = 1;
92
 
93
  /* Configure for inter-character timer being unused. */
94
  tty_state.c_cc[VTIME] = 0;
95
 
96
  if (tcsetattr (fd, TCSAFLUSH, &tty_state) < 0)
97
    return (-1);
98
 
99
  return 0;
100
}
101
 
102
uint8_t*
103
get_mem (void)
104
{
105
  return mem.raw;
106
}
107
 
108
void
109
get_mem_map (SCARTS_ADDR_CTYPE* start, SCARTS_ADDR_CTYPE* size)
110
{
111
  *start = MINI_UART_BADDR;
112
  *size  = MINI_UART_SIZE;
113
}
114
 
115
uint8_t*
116
get_status (void)
117
{
118
  return &mem.regfile.STATUS;
119
}
120
 
121
int
122
mem_read (SCARTS_ADDR_CTYPE offset, uint8_t *value)
123
{
124
  if (offset >= MINI_UART_SIZE)
125
    return 0;
126
 
127
  switch (offset)
128
  {
129
    /* STATUS_C */
130
    case 0:
131
      /* Reading the STATUS_C register resets the MINI_UART_STATUS_C_EF flag. */
132
      write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_EF, 1);
133
      break;
134
    /* MSG_LO */
135
    case 6:
136
    /* MSG_HI */
137
    case 7:
138
      if (read_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_RBR))
139
      {
140
        /* Reading a received message resets the following flags:
141
         * - MINI_UART_STATUS_C_FE
142
         * - MINI_UART_STATUS_C_PE
143
         * - MINI_UART_STATUS_C_OV
144
         * - MINI_UART_STATUS_C_RBR
145
         * - MINI_UART_STATUS_ERR
146
         */
147
        write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_FE, 0);
148
        write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_PE, 0);
149
        write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_OV, 0);
150
        write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_RBR, 0);
151
        write_bit (mem.regfile.STATUS, MINI_UART_STATUS_ERR, 0);
152
      }
153
 
154
      break;
155
  }
156
 
157
  *value = mem.raw[offset];
158
  return 1;
159
}
160
 
161
int
162
mem_write (SCARTS_ADDR_CTYPE offset, uint8_t value)
163
{
164
  if (offset >= MINI_UART_SIZE)
165
    return 0;
166
 
167
  switch (offset)
168
  {
169
    /* STATUS */
170
    case 0:
171
    /* STATUS_C */
172
    case 1:
173
      /* The STATUS and STATUS_C registers are read-only. */
174
      return 0;
175
    /* CONFIG */
176
    case 2:
177
      /* Write the MINI_UART_CONFIG_LOOW bit to MINI_UART_STATUS_LOOR. */
178
      write_bit (mem.regfile.STATUS, MINI_UART_STATUS_LOOR, read_bit (value, MINI_UART_CONFIG_LOOW));
179
 
180
      /* Check if an interrupt needs to be acknowledged. */
181
      if (read_bit (value, MINI_UART_CONFIG_INTA))
182
      {
183
        write_bit (mem.regfile.STATUS, MINI_UART_STATUS_INT, 0);
184
        write_bit (value, MINI_UART_CONFIG_INTA, 0);
185
      }
186
      break;
187
    /* CMD */
188
    case 5:
189
      switch (value & UART_CMD_ASA_BITMASK)
190
      {
191
        /* Start the transmitter. */
192
        case UART_CMD_ASA_TxStart:
193
          /* Simulate some delay before starting the transmission. */
194
          txCnt = 1;
195
          break;
196
        /* Enable the receiver. */
197
        case UART_CMD_ASA_RxEnable:
198
          /* Reset all error flags. */
199
          write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_FE, 0);
200
          write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_PE, 0);
201
          write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_OV, 0);
202
          write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_RBR, 0);
203
          write_bit (mem.regfile.STATUS, MINI_UART_STATUS_ERR, 0);
204
          rxEnabled = 1;
205
          break;
206
        /* Stop the receiver. */
207
        case UART_CMD_ASA_RxDisable:
208
          rxEnabled = 0;
209
          break;
210
      }
211
 
212
      break;
213
    case 6:
214
      txMsgChanged = 1;
215
      break;
216
  }
217
 
218
  mem.raw[offset] = value;
219
  return 1;
220
}
221
 
222
void
223
reset (void)
224
{
225
  memset (mem.raw, 0, MINI_UART_SIZE);
226
}
227
 
228
void
229
tick (SCARTS_ADDR_CTYPE pc)
230
{
231
  char c;
232
 
233
  if (txMsgChanged && --txCnt == 0)
234
  {
235
    if (write (fdm, &mem.regfile.MSG_LO, 1) == -1)
236
      fprintf (stderr, "Error writing to pseudo-terminal master device: %s\n", strerror (errno));
237
 
238
    if ((mem.regfile.CMD & UART_CMD_ES_MASK) == UART_CMD_ES_TxStarted)
239
      set_event_flag ();
240
 
241
    /* The transmitter is ready to transmit data. */
242
    write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_TBR, 1);
243
 
244
    txCnt = 1;
245
    txMsgChanged = 0;
246
  }
247
 
248
  /* Check if there is something to receive. */
249
  if (rxEnabled && !read_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_RBR) && read (fdm, &c, 1) > 0)
250
  {
251
    mem.regfile.MSG_HI = 0;
252
    mem.regfile.MSG_LO = c;
253
 
254
    write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_RBR, 1);
255
 
256
    if ((mem.regfile.CMD & UART_CMD_ES_MASK) == UART_CMD_ES_RxComplete
257
     || (mem.regfile.CMD & UART_CMD_ES_MASK) == UART_CMD_ES_StartBitRec)
258
      set_event_flag ();
259
  }
260
}
261
 
262
void __attribute__ ((constructor))
263
miniuart_init (void)
264
{
265
  extern char *ptsname ();
266
  char *slavename;
267
 
268
  /* Get a handle to the pseudo TTY master at MINIUART_TTY_DEV. */
269
  fdm = open (MINIUART_TTY_DEV, O_RDWR | O_NOCTTY | O_NONBLOCK);
270
  if (fdm == -1)
271
    fprintf (stderr, "Error opening backend device: %s\n", strerror (errno));
272
 
273
  if (stty_raw (fdm) != 0)
274
    fprintf (stderr, "Error putting serial device in raw mode: %s\n", strerror (errno));
275
 
276
  /* Grant access to the pseudo-terminal slave device. */
277
  if (grantpt (fdm) == -1)
278
    fprintf (stderr, "Error granting access to pseudo-terminal slave device: %s\n", strerror (errno));
279
 
280
  /* Unlock the pseudo-terminal master/slave pair. */
281
  if (unlockpt (fdm) == -1)
282
    fprintf (stderr, "Error unlocking the pseudo-terminal master/slave pair: %s\n", strerror (errno));
283
 
284
  /* Get the name of the pseudo-terminal slave device. */
285
  slavename = ptsname (fdm);
286
  if (slavename == NULL)
287
    fprintf (stderr, "Error getting name of pseudo-terminal slave device.\n");
288
 
289
  /* The transmitter is ready to transmit data. */
290
  write_bit (mem.regfile.STATUS_C, MINI_UART_STATUS_C_TBR, 1);
291
 
292
  fprintf (stdout, "miniUART pseudo-terminal master device: %s\n", MINIUART_TTY_DEV);
293
  fprintf (stdout, "miniUART pseudo-terminal slave device: %s\n", slavename);
294
}
295
 
296
void __attribute__ ((destructor))
297
miniuart_finish (void)
298
{
299
  if (fdm != -1)
300
    close (fdm);
301
}
302
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.