Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  comedi_8254.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * comedi_8254.c
 * Generic 8254 timer/counter support
 * Copyright (C) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
 *
 * Based on 8253.h and various subdevice implementations in comedi drivers.
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
 */


/*
 * Module: comedi_8254
 * Description: Generic 8254 timer/counter support
 * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
 * Updated: Thu Jan 8 16:45:45 MST 2015
 * Status: works
 *
 * This module is not used directly by end-users. Rather, it is used by other
 * drivers to provide support for an 8254 Programmable Interval Timer. These
 * counters are typically used to generate the pacer clock used for data
 * acquisition. Some drivers also expose the counters for general purpose use.
 *
 * This module provides the following basic functions:
 *
 * comedi_8254_io_alloc() / comedi_8254_mm_alloc()
 * Initializes this module to access the 8254 registers. The _mm version
 * sets up the module for MMIO register access; the _io version sets it
 * up for PIO access.  These functions return a pointer to a struct
 * comedi_8254 on success, or an ERR_PTR value on failure.  The pointer
 * returned from these functions is normally stored in the comedi_device
 * dev->pacer and will be freed by the comedi core during the driver
 * (*detach). If a driver has multiple 8254 devices, they need to be
 * stored in the drivers private data and freed when the driver is
 * detached.  If the ERR_PTR value is stored, code should check the
 * pointer value with !IS_ERR(pointer) before freeing.
 *
 * NOTE: The counters are reset by setting them to I8254_MODE0 as part of
 * this initialization.
 *
 * comedi_8254_set_mode()
 * Sets a counters operation mode:
 * I8254_MODE0 Interrupt on terminal count
 * I8254_MODE1 Hardware retriggerable one-shot
 * I8254_MODE2 Rate generator
 * I8254_MODE3 Square wave mode
 * I8254_MODE4 Software triggered strobe
 * I8254_MODE5 Hardware triggered strobe (retriggerable)
 *
 * In addition I8254_BCD and I8254_BINARY specify the counting mode:
 * I8254_BCD BCD counting
 * I8254_BINARY Binary counting
 *
 * comedi_8254_write()
 * Writes an initial value to a counter.
 *
 * The largest possible initial count is 0; this is equivalent to 2^16
 * for binary counting and 10^4 for BCD counting.
 *
 * NOTE: The counter does not stop when it reaches zero. In Mode 0, 1, 4,
 * and 5 the counter "wraps around" to the highest count, either 0xffff
 * for binary counting or 9999 for BCD counting, and continues counting.
 * Modes 2 and 3 are periodic; the counter reloads itself with the initial
 * count and continues counting from there.
 *
 * comedi_8254_read()
 * Reads the current value from a counter.
 *
 * comedi_8254_status()
 * Reads the status of a counter.
 *
 * comedi_8254_load()
 * Sets a counters operation mode and writes the initial value.
 *
 * Typically the pacer clock is created by cascading two of the 16-bit counters
 * to create a 32-bit rate generator (I8254_MODE2). These functions are
 * provided to handle the cascaded counters:
 *
 * comedi_8254_ns_to_timer()
 * Calculates the divisor value needed for a single counter to generate
 * ns timing.
 *
 * comedi_8254_cascade_ns_to_timer()
 * Calculates the two divisor values needed to the generate the pacer
 * clock (in ns).
 *
 * comedi_8254_update_divisors()
 * Transfers the intermediate divisor values to the current divisors.
 *
 * comedi_8254_pacer_enable()
 * Programs the mode of the cascaded counters and writes the current
 * divisor values.
 *
 * To expose the counters as a subdevice for general purpose use the following
 * functions a provided:
 *
 * comedi_8254_subdevice_init()
 * Initializes a comedi_subdevice to use the 8254 timer.
 *
 * comedi_8254_set_busy()
 * Internally flags a counter as "busy". This is done to protect the
 * counters that are used for the cascaded 32-bit pacer.
 *
 * The subdevice provides (*insn_read) and (*insn_write) operations to read
 * the current value and write an initial value to a counter. A (*insn_config)
 * operation is also provided to handle the following comedi instructions:
 *
 * INSN_CONFIG_SET_COUNTER_MODE calls comedi_8254_set_mode()
 * INSN_CONFIG_8254_READ_STATUS calls comedi_8254_status()
 *
 * The (*insn_config) member of comedi_8254 can be initialized by the external
 * driver to handle any additional instructions.
 *
 * NOTE: Gate control, clock routing, and any interrupt handling for the
 * counters is not handled by this module. These features are driver dependent.
 */


#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/comedi/comedidev.h>
#include <linux/comedi/comedi_8254.h>

#ifdef CONFIG_HAS_IOPORT

static unsigned int i8254_io8_cb(struct comedi_8254 *i8254, int dir,
    unsigned int reg, unsigned int val)
{
 unsigned long iobase = i8254->context;
 unsigned int reg_offset = (reg * I8254_IO8) << i8254->regshift;

 if (dir) {
  outb(val, iobase + reg_offset);
  return 0;
 } else {
  return inb(iobase + reg_offset);
 }
}

static unsigned int i8254_io16_cb(struct comedi_8254 *i8254, int dir,
      unsigned int reg, unsigned int val)
{
 unsigned long iobase = i8254->context;
 unsigned int reg_offset = (reg * I8254_IO16) << i8254->regshift;

 if (dir) {
  outw(val, iobase + reg_offset);
  return 0;
 } else {
  return inw(iobase + reg_offset);
 }
}

static unsigned int i8254_io32_cb(struct comedi_8254 *i8254, int dir,
      unsigned int reg, unsigned int val)
{
 unsigned long iobase = i8254->context;
 unsigned int reg_offset = (reg * I8254_IO32) << i8254->regshift;

 if (dir) {
  outl(val, iobase + reg_offset);
  return 0;
 } else {
  return inl(iobase + reg_offset);
 }
}

#endif /* CONFIG_HAS_IOPORT */

static unsigned int i8254_mmio8_cb(struct comedi_8254 *i8254, int dir,
       unsigned int reg, unsigned int val)
{
 void __iomem *mmiobase = (void __iomem *)i8254->context;
 unsigned int reg_offset = (reg * I8254_IO8) << i8254->regshift;

 if (dir) {
  writeb(val, mmiobase + reg_offset);
  return 0;
 } else {
  return readb(mmiobase + reg_offset);
 }
}

static unsigned int i8254_mmio16_cb(struct comedi_8254 *i8254, int dir,
        unsigned int reg, unsigned int val)
{
 void __iomem *mmiobase = (void __iomem *)i8254->context;
 unsigned int reg_offset = (reg * I8254_IO16) << i8254->regshift;

 if (dir) {
  writew(val, mmiobase + reg_offset);
  return 0;
 } else {
  return readw(mmiobase + reg_offset);
 }
}

static unsigned int i8254_mmio32_cb(struct comedi_8254 *i8254, int dir,
        unsigned int reg, unsigned int val)
{
 void __iomem *mmiobase = (void __iomem *)i8254->context;
 unsigned int reg_offset = (reg * I8254_IO32) << i8254->regshift;

 if (dir) {
  writel(val, mmiobase + reg_offset);
  return 0;
 } else {
  return readl(mmiobase + reg_offset);
 }
}

static unsigned int __i8254_read(struct comedi_8254 *i8254, unsigned int reg)
{
 return 0xff & i8254->iocb(i8254, 0, reg, 0);
}

static void __i8254_write(struct comedi_8254 *i8254,
     unsigned int val, unsigned int reg)
{
 i8254->iocb(i8254, 1, reg, val);
}

/**
 * comedi_8254_status - return the status of a counter
 * @i8254: comedi_8254 struct for the timer
 * @counter: the counter number
 */

unsigned int comedi_8254_status(struct comedi_8254 *i8254, unsigned int counter)
{
 unsigned int cmd;

 if (counter > 2)
  return 0;

 cmd = I8254_CTRL_READBACK_STATUS | I8254_CTRL_READBACK_SEL_CTR(counter);
 __i8254_write(i8254, cmd, I8254_CTRL_REG);

 return __i8254_read(i8254, counter);
}
EXPORT_SYMBOL_GPL(comedi_8254_status);

/**
 * comedi_8254_read - read the current counter value
 * @i8254: comedi_8254 struct for the timer
 * @counter: the counter number
 */

unsigned int comedi_8254_read(struct comedi_8254 *i8254, unsigned int counter)
{
 unsigned int val;

 if (counter > 2)
  return 0;

 /* latch counter */
 __i8254_write(i8254, I8254_CTRL_SEL_CTR(counter) | I8254_CTRL_LATCH,
        I8254_CTRL_REG);

 /* read LSB then MSB */
 val = __i8254_read(i8254, counter);
 val |= (__i8254_read(i8254, counter) << 8);

 return val;
}
EXPORT_SYMBOL_GPL(comedi_8254_read);

/**
 * comedi_8254_write - load a 16-bit initial counter value
 * @i8254: comedi_8254 struct for the timer
 * @counter: the counter number
 * @val: the initial value
 */

void comedi_8254_write(struct comedi_8254 *i8254,
         unsigned int counter, unsigned int val)
{
 unsigned int byte;

 if (counter > 2)
  return;
 if (val > 0xffff)
  return;

 /* load LSB then MSB */
 byte = val & 0xff;
 __i8254_write(i8254, byte, counter);
 byte = (val >> 8) & 0xff;
 __i8254_write(i8254, byte, counter);
}
EXPORT_SYMBOL_GPL(comedi_8254_write);

/**
 * comedi_8254_set_mode - set the mode of a counter
 * @i8254: comedi_8254 struct for the timer
 * @counter: the counter number
 * @mode: the I8254_MODEx and I8254_BCD|I8254_BINARY
 */

int comedi_8254_set_mode(struct comedi_8254 *i8254, unsigned int counter,
    unsigned int mode)
{
 unsigned int byte;

 if (counter > 2)
  return -EINVAL;
 if (mode > (I8254_MODE5 | I8254_BCD))
  return -EINVAL;

 byte = I8254_CTRL_SEL_CTR(counter) | /* select counter */
        I8254_CTRL_LSB_MSB |  /* load LSB then MSB */
        mode;    /* mode and BCD|binary */
 __i8254_write(i8254, byte, I8254_CTRL_REG);

 return 0;
}
EXPORT_SYMBOL_GPL(comedi_8254_set_mode);

/**
 * comedi_8254_load - program the mode and initial count of a counter
 * @i8254: comedi_8254 struct for the timer
 * @counter: the counter number
 * @mode: the I8254_MODEx and I8254_BCD|I8254_BINARY
 * @val: the initial value
 */

int comedi_8254_load(struct comedi_8254 *i8254, unsigned int counter,
       unsigned int val, unsigned int mode)
{
 if (counter > 2)
  return -EINVAL;
 if (val > 0xffff)
  return -EINVAL;
 if (mode > (I8254_MODE5 | I8254_BCD))
  return -EINVAL;

 comedi_8254_set_mode(i8254, counter, mode);
 comedi_8254_write(i8254, counter, val);

 return 0;
}
EXPORT_SYMBOL_GPL(comedi_8254_load);

/**
 * comedi_8254_pacer_enable - set the mode and load the cascaded counters
 * @i8254: comedi_8254 struct for the timer
 * @counter1: the counter number for the first divisor
 * @counter2: the counter number for the second divisor
 * @enable: flag to enable (load) the counters
 */

void comedi_8254_pacer_enable(struct comedi_8254 *i8254,
         unsigned int counter1,
         unsigned int counter2,
         bool enable)
{
 unsigned int mode;

 if (counter1 > 2 || counter2 > 2 || counter1 == counter2)
  return;

 if (enable)
  mode = I8254_MODE2 | I8254_BINARY;
 else
  mode = I8254_MODE0 | I8254_BINARY;

 comedi_8254_set_mode(i8254, counter1, mode);
 comedi_8254_set_mode(i8254, counter2, mode);

 if (enable) {
  /*
 * Divisors are loaded second counter then first counter to
 * avoid possible issues with the first counter expiring
 * before the second counter is loaded.
 */

  comedi_8254_write(i8254, counter2, i8254->divisor2);
  comedi_8254_write(i8254, counter1, i8254->divisor1);
 }
}
EXPORT_SYMBOL_GPL(comedi_8254_pacer_enable);

/**
 * comedi_8254_update_divisors - update the divisors for the cascaded counters
 * @i8254: comedi_8254 struct for the timer
 */

void comedi_8254_update_divisors(struct comedi_8254 *i8254)
{
 /* masking is done since counter maps zero to 0x10000 */
 i8254->divisor = i8254->next_div & 0xffff;
 i8254->divisor1 = i8254->next_div1 & 0xffff;
 i8254->divisor2 = i8254->next_div2 & 0xffff;
}
EXPORT_SYMBOL_GPL(comedi_8254_update_divisors);

/**
 * comedi_8254_cascade_ns_to_timer - calculate the cascaded divisor values
 * @i8254: comedi_8254 struct for the timer
 * @nanosec: the desired ns time
 * @flags: comedi_cmd flags
 */

void comedi_8254_cascade_ns_to_timer(struct comedi_8254 *i8254,
         unsigned int *nanosec,
         unsigned int flags)
{
 unsigned int d1 = i8254->next_div1 ? i8254->next_div1 : I8254_MAX_COUNT;
 unsigned int d2 = i8254->next_div2 ? i8254->next_div2 : I8254_MAX_COUNT;
 unsigned int div = d1 * d2;
 unsigned int ns_lub = 0xffffffff;
 unsigned int ns_glb = 0;
 unsigned int d1_lub = 0;
 unsigned int d1_glb = 0;
 unsigned int d2_lub = 0;
 unsigned int d2_glb = 0;
 unsigned int start;
 unsigned int ns;
 unsigned int ns_low;
 unsigned int ns_high;

 /* exit early if everything is already correct */
 if (div * i8254->osc_base == *nanosec &&
     d1 > 1 && d1 <= I8254_MAX_COUNT &&
     d2 > 1 && d2 <= I8254_MAX_COUNT &&
     /* check for overflow */
     div > d1 && div > d2 &&
     div * i8254->osc_base > div &&
     div * i8254->osc_base > i8254->osc_base)
  return;

 div = *nanosec / i8254->osc_base;
 d2 = I8254_MAX_COUNT;
 start = div / d2;
 if (start < 2)
  start = 2;
 for (d1 = start; d1 <= div / d1 + 1 && d1 <= I8254_MAX_COUNT; d1++) {
  for (d2 = div / d1;
       d1 * d2 <= div + d1 + 1 && d2 <= I8254_MAX_COUNT; d2++) {
   ns = i8254->osc_base * d1 * d2;
   if (ns <= *nanosec && ns > ns_glb) {
    ns_glb = ns;
    d1_glb = d1;
    d2_glb = d2;
   }
   if (ns >= *nanosec && ns < ns_lub) {
    ns_lub = ns;
    d1_lub = d1;
    d2_lub = d2;
   }
  }
 }

 switch (flags & CMDF_ROUND_MASK) {
 case CMDF_ROUND_NEAREST:
 default:
  ns_high = d1_lub * d2_lub * i8254->osc_base;
  ns_low = d1_glb * d2_glb * i8254->osc_base;
  if (ns_high - *nanosec < *nanosec - ns_low) {
   d1 = d1_lub;
   d2 = d2_lub;
  } else {
   d1 = d1_glb;
   d2 = d2_glb;
  }
  break;
 case CMDF_ROUND_UP:
  d1 = d1_lub;
  d2 = d2_lub;
  break;
 case CMDF_ROUND_DOWN:
  d1 = d1_glb;
  d2 = d2_glb;
  break;
 }

 *nanosec = d1 * d2 * i8254->osc_base;
 i8254->next_div1 = d1;
 i8254->next_div2 = d2;
}
EXPORT_SYMBOL_GPL(comedi_8254_cascade_ns_to_timer);

/**
 * comedi_8254_ns_to_timer - calculate the divisor value for nanosec timing
 * @i8254: comedi_8254 struct for the timer
 * @nanosec: the desired ns time
 * @flags: comedi_cmd flags
 */

void comedi_8254_ns_to_timer(struct comedi_8254 *i8254,
        unsigned int *nanosec, unsigned int flags)
{
 unsigned int divisor;

 switch (flags & CMDF_ROUND_MASK) {
 default:
 case CMDF_ROUND_NEAREST:
  divisor = DIV_ROUND_CLOSEST(*nanosec, i8254->osc_base);
  break;
 case CMDF_ROUND_UP:
  divisor = DIV_ROUND_UP(*nanosec, i8254->osc_base);
  break;
 case CMDF_ROUND_DOWN:
  divisor = *nanosec / i8254->osc_base;
  break;
 }
 if (divisor < 2)
  divisor = 2;
 if (divisor > I8254_MAX_COUNT)
  divisor = I8254_MAX_COUNT;

 *nanosec = divisor * i8254->osc_base;
 i8254->next_div = divisor;
}
EXPORT_SYMBOL_GPL(comedi_8254_ns_to_timer);

/**
 * comedi_8254_set_busy - set/clear the "busy" flag for a given counter
 * @i8254: comedi_8254 struct for the timer
 * @counter: the counter number
 * @busy: set/clear flag
 */

void comedi_8254_set_busy(struct comedi_8254 *i8254,
     unsigned int counter, bool busy)
{
 if (counter < 3)
  i8254->busy[counter] = busy;
}
EXPORT_SYMBOL_GPL(comedi_8254_set_busy);

static int comedi_8254_insn_read(struct comedi_device *dev,
     struct comedi_subdevice *s,
     struct comedi_insn *insn,
     unsigned int *data)
{
 struct comedi_8254 *i8254 = s->private;
 unsigned int chan = CR_CHAN(insn->chanspec);
 int i;

 if (i8254->busy[chan])
  return -EBUSY;

 for (i = 0; i < insn->n; i++)
  data[i] = comedi_8254_read(i8254, chan);

 return insn->n;
}

static int comedi_8254_insn_write(struct comedi_device *dev,
      struct comedi_subdevice *s,
      struct comedi_insn *insn,
      unsigned int *data)
{
 struct comedi_8254 *i8254 = s->private;
 unsigned int chan = CR_CHAN(insn->chanspec);

 if (i8254->busy[chan])
  return -EBUSY;

 if (insn->n)
  comedi_8254_write(i8254, chan, data[insn->n - 1]);

 return insn->n;
}

static int comedi_8254_insn_config(struct comedi_device *dev,
       struct comedi_subdevice *s,
       struct comedi_insn *insn,
       unsigned int *data)
{
 struct comedi_8254 *i8254 = s->private;
 unsigned int chan = CR_CHAN(insn->chanspec);
 int ret;

 if (i8254->busy[chan])
  return -EBUSY;

 switch (data[0]) {
 case INSN_CONFIG_RESET:
  ret = comedi_8254_set_mode(i8254, chan,
        I8254_MODE0 | I8254_BINARY);
  if (ret)
   return ret;
  break;
 case INSN_CONFIG_SET_COUNTER_MODE:
  ret = comedi_8254_set_mode(i8254, chan, data[1]);
  if (ret)
   return ret;
  break;
 case INSN_CONFIG_8254_READ_STATUS:
  data[1] = comedi_8254_status(i8254, chan);
  break;
 default:
  /*
 * If available, call the driver provided (*insn_config)
 * to handle any driver implemented instructions.
 */

  if (i8254->insn_config)
   return i8254->insn_config(dev, s, insn, data);

  return -EINVAL;
 }

 return insn->n;
}

/**
 * comedi_8254_subdevice_init - initialize a comedi_subdevice for the 8254 timer
 * @s: comedi_subdevice struct
 * @i8254: comedi_8254 struct
 */

void comedi_8254_subdevice_init(struct comedi_subdevice *s,
    struct comedi_8254 *i8254)
{
 s->type  = COMEDI_SUBD_COUNTER;
 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 s->n_chan = 3;
 s->maxdata = 0xffff;
 s->range_table = &range_unknown;
 s->insn_read = comedi_8254_insn_read;
 s->insn_write = comedi_8254_insn_write;
 s->insn_config = comedi_8254_insn_config;

 s->private = i8254;
}
EXPORT_SYMBOL_GPL(comedi_8254_subdevice_init);

static struct comedi_8254 *__i8254_init(comedi_8254_iocb_fn *iocb,
     unsigned long context,
     unsigned int osc_base,
     unsigned int iosize,
     unsigned int regshift)
{
 struct comedi_8254 *i8254;
 int i;

 /* sanity check that the iosize is valid */
 if (!(iosize == I8254_IO8 || iosize == I8254_IO16 ||
       iosize == I8254_IO32))
  return ERR_PTR(-EINVAL);

 if (!iocb)
  return ERR_PTR(-EINVAL);

 i8254 = kzalloc(sizeof(*i8254), GFP_KERNEL);
 if (!i8254)
  return ERR_PTR(-ENOMEM);

 i8254->iocb = iocb;
 i8254->context = context;
 i8254->iosize = iosize;
 i8254->regshift = regshift;

 /* default osc_base to the max speed of a generic 8254 timer */
 i8254->osc_base = osc_base ? osc_base : I8254_OSC_BASE_10MHZ;

 /* reset all the counters by setting them to I8254_MODE0 */
 for (i = 0; i < 3; i++)
  comedi_8254_set_mode(i8254, i, I8254_MODE0 | I8254_BINARY);

 return i8254;
}

#ifdef CONFIG_HAS_IOPORT

/**
 * comedi_8254_io_alloc - allocate and initialize the 8254 device for pio access
 * @iobase: port I/O base address
 * @osc_base: base time of the counter in ns
 * OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
 * @iosize: I/O register size
 * @regshift: register gap shift
 *
 * Return: A pointer to a struct comedi_8254 or an ERR_PTR value.
 */

struct comedi_8254 *comedi_8254_io_alloc(unsigned long iobase,
      unsigned int osc_base,
      unsigned int iosize,
      unsigned int regshift)
{
 comedi_8254_iocb_fn *iocb;

 switch (iosize) {
 case I8254_IO8:
  iocb = i8254_io8_cb;
  break;
 case I8254_IO16:
  iocb = i8254_io16_cb;
  break;
 case I8254_IO32:
  iocb = i8254_io32_cb;
  break;
 default:
  return ERR_PTR(-EINVAL);
 }
 return __i8254_init(iocb, iobase, osc_base, iosize, regshift);
}
EXPORT_SYMBOL_GPL(comedi_8254_io_alloc);

#endif /* CONFIG_HAS_IOPORT */

/**
 * comedi_8254_mm_alloc - allocate and initialize the 8254 device for mmio access
 * @mmio: memory mapped I/O base address
 * @osc_base: base time of the counter in ns
 * OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
 * @iosize: I/O register size
 * @regshift: register gap shift
 *
 * Return: A pointer to a struct comedi_8254 or an ERR_PTR value.
 */

struct comedi_8254 *comedi_8254_mm_alloc(void __iomem *mmio,
      unsigned int osc_base,
      unsigned int iosize,
      unsigned int regshift)
{
 comedi_8254_iocb_fn *iocb;

 switch (iosize) {
 case I8254_IO8:
  iocb = i8254_mmio8_cb;
  break;
 case I8254_IO16:
  iocb = i8254_mmio16_cb;
  break;
 case I8254_IO32:
  iocb = i8254_mmio32_cb;
  break;
 default:
  return ERR_PTR(-EINVAL);
 }
 return __i8254_init(iocb, (unsigned long)mmio, osc_base, iosize, regshift);
}
EXPORT_SYMBOL_GPL(comedi_8254_mm_alloc);

static int __init comedi_8254_module_init(void)
{
 return 0;
}
module_init(comedi_8254_module_init);

static void __exit comedi_8254_module_exit(void)
{
}
module_exit(comedi_8254_module_exit);

MODULE_AUTHOR("H Hartley Sweeten ");
MODULE_DESCRIPTION("Comedi: Generic 8254 timer/counter support");
MODULE_LICENSE("GPL");

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge