Ejemplo n.º 1
0
void _ltc3350_init_i2c(void) {
  unlock_config();

  // Disable I2C4 Module
  I2C4CONbits.ON = 0;

  // SDA4
  TRISGbits.TRISG7 = OUTPUT;
  LATGbits.LATG7 = 0;
  TRISGbits.TRISG7 = INPUT;

  TRISGbits.TRISG8 = OUTPUT;
  LATGbits.LATG8 = 0;
  TRISGbits.TRISG8 = INPUT;

  //ANSELGbits.ANSG7 = DIG_INPUT;
  CNPUGbits.CNPUG7 = 1;

  // SCL4
  //TRISGbits.TRISG8 = OUTPUT;
  CNPUGbits.CNPUG8 = 1;

  // Disable interrupts
  IEC5CLR = _IEC5_I2C4MIE_MASK;
  IEC5CLR = _IEC5_I2C4SIE_MASK;
  IEC5CLR = _IEC5_I2C4BIE_MASK;
  IFS5CLR = _IFS5_I2C4MIF_MASK;
  IFS5CLR = _IFS5_I2C4SIF_MASK;
  IFS5CLR = _IFS5_I2C4BIF_MASK;

  /**
   * Baud rate (400kHz desired)
   * 
   * I2CxBRG = (F_FBCLK2 * ((1 / (2 * F_SCL)) - T_PGD)) - 2
   * I2CxBRG = (100Mhz * ((1.25 uS - 104nS)) - 2
   * I2CxBRG = 112
   */
  //I2C4BRG = 0x70; 400
  //I2C4BRG = 0x1E8; 100
  I2C4BRG = 0x9B8; // 20

  I2C4ADD = PIC_DEV_ADDR;

  // I2C4CON
  I2C4CONbits.A10M = 0; // 7-bit Slave Address
  I2C4CONbits.SMEN = 1; // Compliant with SMBus Spec

  // Enable I2C4 Module
  I2C4CONbits.ON = 1;

  lock_config();
}
Ejemplo n.º 2
0
void init_spi() {
  unlock_config();

  // Initialize SDI1/SDO1 PPS pins
  CFGCONbits.IOLOCK = 0;
  TRISBbits.TRISB9 = INPUT;
  SDI1Rbits.SDI1R = 0b0101; // RPB9
  TRISBbits.TRISB10 = OUTPUT;
  RPB10Rbits.RPB10R = 0b0101; // SDO1
  CFGCONbits.IOLOCK = 1;

  // Disable interrupts
  IEC3bits.SPI1EIE = 0;
  IEC3bits.SPI1RXIE = 0;
  IEC3bits.SPI1TXIE = 0;

  // Disable SPI1 module
  SPI1CONbits.ON = 0;

  // Clear receive buffer
  SPI1BUF = 0;

  // Use standard buffer mode
  SPI1CONbits.ENHBUF = 0;

  /**
   * F_SCK = F_PBCLK2 / (2 * (SPI1BRG + 1))
   * F_SCK = 100Mhz / (2 * (4 + 1))
   * F_SCK = 10Mhz
   */

  // Set the baud rate (see above equation)
  SPI1BRG = 4;

  SPI1STATbits.SPIROV = 0;

  SPI1CONbits.MCLKSEL = 0; // Master Clock Enable bit (PBCLK2 is used by the Baud Rate Generator)
  SPI1CONbits.SIDL = 0;    // Stop in Idle Mode bit (Continue operation in Idle mode)
  SPI1CONbits.MODE32 = 0;  // 32/16-Bit Communication Select bits (16-bit)
  SPI1CONbits.MODE16 = 1;  // 32/16-Bit Communication Select bits (16-bit)
  SPI1CONbits.MSTEN = 1;   // Master Mode Enable bit (Master mode)
  SPI1CONbits.CKE = 1;     // SPI Clock Edge Select bit (Serial output data changes on transition from active clock state to idle clock state)

  // Enable SPI1 module
  SPI1CONbits.ON = 1;

  lock_config();
}
Ejemplo n.º 3
0
void init_general(void) {
  unlock_config();

  // PRECON
  PRECONbits.PFMSECEN = 0;  // Flash SEC Interrupt Enable (Do not generate an interrupt when the PFMSEC bit is set)
  PRECONbits.PREFEN = 0b11; // Predictive Prefetch Enable (Enable predictive prefetch for any address)
  PRECONbits.PFMWS = 0b010; // PFM Access Time Defined in Terms of SYSCLK Wait States (Two wait states)

  // CFGCON
  CFGCONbits.DMAPRI = 0;    // DMA Read and DMA Write Arbitration Priority to SRAM (DMA uses Least Recently Serviced Arbitration)
  CFGCONbits.CPUPRI = 0;    // CPU Arbitration Priority to SRAM When Servicing an Interrupt (CPU uses Least Recently Serviced Arbitration)
  CFGCONbits.ICACLK = 0;    // Input Capture Alternate Clock Selection (All Input Capture modules use Timer2/3 as their timebase clock)
  CFGCONbits.OCACLK = 0;    // Output Compare Alternate Clock Selection (All Output Compare modules use Timer2/3 as their timebase clock)
  CFGCONbits.IOLOCK = 1;    // Peripheral Pin Select Lock (Peripheral Pin Select is locked. Writes to PPS registers are not allowed)
  CFGCONbits.PMDLOCK = 1;   // Peripheral Module Disable (Peripheral module is locked. Writes to PMD registers are not allowed)
  CFGCONbits.PGLOCK = 1;    // Permission Group Lock (Permission Group registers are locked. Writes to PG registers are not allowed)
  CFGCONbits.USBSSEN = 1;   // USB Suspend Sleep Enable (USB PHY clock is shut down when Sleep mode is active)
  CFGCONbits.IOANCPN = 0;   // I/O Analog Charge Pump Enable (Charge pump disabled)
  CFGCONbits.ECCCON = 0b10; // Flash ECC Configuration (ECC and dynamic ECC are disabled (ECCCON<1:0> bits are locked))
  CFGCONbits.JTAGEN = 0;    // JTAG Port Enable (Disable the JTAG port)
  CFGCONbits.TROEN = 0;     // Trace Output Enable (Disable trace outputs and stop trace clock)
  CFGCONbits.TDOEN = 1;     // TDO Enable for 2-Wire JTAG (2-wire JTAG protocol uses TDO)

  // CFGPG
  CFGPGbits.CRYPTPG = 0; // Crypto Engine Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.FCPG = 0;    // Flash Control Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.SQI1PG = 0;  // SQI Module Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.ETHPG = 0;   // Ethernet Module Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.CAN2PG = 0;  // CAN2 Module Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.CAN1PG = 0;  // CAN1 Module Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.USBPG = 0;   // USB Module Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.DMAPG = 0;   // DMA Module Permission Group (Initiator is assigned to Permission Group 0)
  CFGPGbits.CPUPG = 0;   // CPU Permission Group (Initiator is assigned to Permission Group 0)

  lock_config();
}
Ejemplo n.º 4
0
void init_timer1(void) {
  unlock_config();

  // Disable TMR1
  T1CONbits.ON = 0; // Timer On (Timer is disabled)

  // T1CON
  T1CONbits.TCS = 0;      // Timer Clock Source Select (Internal peripheral clock)
  T1CONbits.SIDL = 0;     // Stop in Idle Mode (Continue operation even in Idle mode)
  T1CONbits.TWDIS = 1;    // Asynchronous Timer Write Disable (Writes to TMR1 are ignored until pending write operation completes)
  T1CONbits.TGATE = 0;    // Timer Gated Time Accumulation Enable (Gated time accumulation is disabled)
  T1CONbits.TCKPS = 0b10; // Timer Input Clock Prescale Select (1:64 prescale value)

  // TMR1
  TMR1 = 0; // TMR1 Count Register (0)

  /**
   * The clock source is PBCLK3, which is configured to run at SYSCLOCK / 50.
   * Currently, this gives a speed of 4Mhz. TMR1 uses a 1:64 prescale, meaning
   * 1 second should be equal to 4000000 / 64 == 62500 TMR1 cycles.
   */

  // PR1
  PR1 = 0xF424; // PR1 Period Register (62500)

  // Set up TMR1 Interrupt
  IFS0bits.T1IF = 0; // TMR1 Interrupt Flag Status (No interrupt request has occured)
  IPC1bits.T1IP = 7; // TMR1 Interrupt Priority (Interrupt priority is 7)
  IPC1bits.T1IS = 3; // TMR1 Interrupt Subpriority (Interrupt subpriority is 3)
  IEC0bits.T1IE = 1; // TMR1 Interrupt Enable Control (Interrupt is enabled)

  // Enable TMR1
  T1CONbits.ON = 1; // Timer On (Timer is enabled)

  lock_config();
}
Ejemplo n.º 5
0
/* ioctl routine */
int
vinumioctl(dev_t dev,
    u_long cmd,
    caddr_t data,
    int flag,
    struct thread *td)
{
    unsigned int objno;
    int error = 0;
    struct sd *sd;
    struct plex *plex;
    struct volume *vol;
    unsigned int index;					    /* for transferring config info */
    unsigned int sdno;					    /* for transferring config info */
    int fe;						    /* free list element number */
    struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) data; /* struct to return */

    /* First, decide what we're looking at */
    switch (DEVTYPE(dev)) {
    case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */
	ioctl_reply = (struct _ioctl_reply *) data;	    /* save the address to reply to */
	switch (cmd) {
#ifdef VINUMDEBUG
	case VINUM_DEBUG:
	    if (((struct debuginfo *) data)->changeit)	    /* change debug settings */
		debug = (((struct debuginfo *) data)->param);
	    else {
		if (debug & DEBUG_REMOTEGDB)
		    boothowto |= RB_GDB;		    /* serial debug line */
		else
		    boothowto &= ~RB_GDB;		    /* local ddb */
		Debugger("vinum debug");
	    }
	    ioctl_reply = (struct _ioctl_reply *) data;	    /* reinstate the address to reply to */
	    ioctl_reply->error = 0;
	    return 0;
#endif

	case VINUM_CREATE:				    /* create a vinum object */
	    error = lock_config();			    /* get the config for us alone */
	    if (error)					    /* can't do it, */
		return error;				    /* give up */
	    error = setjmp(command_fail);		    /* come back here on error */
	    if (error == 0)				    /* first time, */
		ioctl_reply->error = parse_user_config((char *) data, /* update the config */
		    &keyword_set);
	    else if (ioctl_reply->error == 0) {		    /* longjmp, but no error status */
		ioctl_reply->error = EINVAL;		    /* note that something's up */
		ioctl_reply->msg[0] = '\0';		    /* no message? */
	    }
	    unlock_config();
	    return 0;					    /* must be 0 to return the real error info */

	case VINUM_GETCONFIG:				    /* get the configuration information */
	    bcopy(&vinum_conf, data, sizeof(vinum_conf));
	    return 0;

	    /* start configuring the subsystem */
	case VINUM_STARTCONFIG:
	    return start_config(*(int *) data);		    /* just lock it.  Parameter is 'force' */

	    /*
	     * Move the individual parts of the config to user space.
	     *
	     * Specify the index of the object in the first word of data,
	     * and return the object there
	     */
	case VINUM_DRIVECONFIG:
	    index = *(int *) data;			    /* get the index */
	    if (index >= (unsigned) vinum_conf.drives_allocated) /* can't do it */
		return ENXIO;				    /* bang */
	    bcopy(&DRIVE[index], data, sizeof(struct _drive)); /* copy the config item out */
	    return 0;

	case VINUM_SDCONFIG:
	    index = *(int *) data;			    /* get the index */
	    if (index >= (unsigned) vinum_conf.subdisks_allocated) /* can't do it */
		return ENXIO;				    /* bang */
	    bcopy(&SD[index], data, sizeof(struct _sd));    /* copy the config item out */
	    return 0;

	case VINUM_PLEXCONFIG:
	    index = *(int *) data;			    /* get the index */
	    if (index >= (unsigned) vinum_conf.plexes_allocated) /* can't do it */
		return ENXIO;				    /* bang */
	    bcopy(&PLEX[index], data, sizeof(struct _plex)); /* copy the config item out */
	    return 0;

	case VINUM_VOLCONFIG:
	    index = *(int *) data;			    /* get the index */
	    if (index >= (unsigned) vinum_conf.volumes_allocated) /* can't do it */
		return ENXIO;				    /* bang */
	    bcopy(&VOL[index], data, sizeof(struct _volume)); /* copy the config item out */
	    return 0;

	case VINUM_PLEXSDCONFIG:
	    index = *(int *) data;			    /* get the plex index */
	    sdno = ((int *) data)[1];			    /* and the sd index */
	    if ((index >= (unsigned) vinum_conf.plexes_allocated) /* plex doesn't exist */
	    ||(sdno >= PLEX[index].subdisks))		    /* or it doesn't have this many subdisks */
		return ENXIO;				    /* bang */
	    bcopy(&SD[PLEX[index].sdnos[sdno]],		    /* copy the config item out */
		data,
		sizeof(struct _sd));
	    return 0;

	    /*
	     * We get called in two places: one from the
	     * userland config routines, which call us
	     * to complete the config and save it.  This
	     * call supplies the value 0 as a parameter.
	     *
	     * The other place is from the user "saveconfig"
	     * routine, which can only work if we're *not*
	     * configuring.  In this case, supply parameter 1.
	     */
	case VINUM_SAVECONFIG:
	    if (VFLAGS & VF_CONFIGURING) {		    /* must be us, the others are asleep */
		if (*(int *) data == 0)			    /* finish config */
		    finish_config(1);			    /* finish the configuration and update it */
		else
		    return EBUSY;			    /* can't do it now */
	    }
	    save_config();				    /* save configuration to disk */
	    return 0;

	case VINUM_RELEASECONFIG:			    /* release the config */
	    if (VFLAGS & VF_CONFIGURING) {		    /* must be us, the others are asleep */
		finish_config(0);			    /* finish the configuration, don't change it */
		save_config();				    /* save configuration to disk */
	    } else
		error = EINVAL;				    /* release what config? */
	    return error;

	case VINUM_INIT:
	    ioctl_reply = (struct _ioctl_reply *) data;	    /* reinstate the address to reply to */
	    ioctl_reply->error = 0;
	    return 0;

	case VINUM_RESETCONFIG:
	    if (vinum_inactive(0)) {			    /* if the volumes are not active */
		/*
		 * Note the open count.  We may be called from v, so we'll be open.
		 * Keep the count so we don't underflow
		 */
		free_vinum(1);				    /* clean up everything */
		log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");
		ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
		ioctl_reply->error = 0;
		return 0;
	    }
	    return EBUSY;

	case VINUM_SETSTATE:
	    setstate((struct vinum_ioctl_msg *) data);	    /* set an object state */
	    return 0;

	    /*
	     * Set state by force, without changing
	     * anything else.
	     */
	case VINUM_SETSTATE_FORCE:
	    setstate_by_force((struct vinum_ioctl_msg *) data);	/* set an object state */
	    return 0;

#ifdef VINUMDEBUG
	case VINUM_MEMINFO:
	    vinum_meminfo(data);
	    return 0;

	case VINUM_MALLOCINFO:
	    return vinum_mallocinfo(data);

	case VINUM_RQINFO:
	    return vinum_rqinfo(data);
#endif

	case VINUM_LABEL:				    /* label a volume */
	    ioctl_reply->error = write_volume_label(*(int *) data); /* index of the volume to label */
	    ioctl_reply->msg[0] = '\0';			    /* no message */
	    return 0;

	case VINUM_REMOVE:
	    remove((struct vinum_ioctl_msg *) data);	    /* remove an object */
	    return 0;

	case VINUM_GETFREELIST:				    /* get a drive free list element */
	    index = *(int *) data;			    /* get the drive index */
	    fe = ((int *) data)[1];			    /* and the free list element */
	    if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */
	    ||(DRIVE[index].state == drive_unallocated))
		return ENODEV;
	    if (fe >= DRIVE[index].freelist_entries)	    /* no such entry */
		return ENOENT;
	    bcopy(&DRIVE[index].freelist[fe],
		data,
		sizeof(struct drive_freelist));
	    return 0;

	case VINUM_RESETSTATS:
	    resetstats((struct vinum_ioctl_msg *) data);    /* reset object stats */
	    return 0;

	    /* attach an object to a superordinate object */
	case VINUM_ATTACH:
	    attachobject((struct vinum_ioctl_msg *) data);
	    return 0;

	    /* detach an object from a superordinate object */
	case VINUM_DETACH:
	    detachobject((struct vinum_ioctl_msg *) data);
	    return 0;

	    /* rename an object */
	case VINUM_RENAME:
	    renameobject((struct vinum_rename_msg *) data);
	    return 0;

	    /* replace an object */
	case VINUM_REPLACE:
	    replaceobject((struct vinum_ioctl_msg *) data);
	    return 0;

	case VINUM_DAEMON:
	    vinum_daemon();				    /* perform the daemon */
	    return 0;

	case VINUM_FINDDAEMON:				    /* check for presence of daemon */
	    return vinum_finddaemon();
	    return 0;

	case VINUM_SETDAEMON:				    /* set daemon flags */
	    return vinum_setdaemonopts(*(int *) data);

	case VINUM_GETDAEMON:				    /* get daemon flags */
	    *(int *) data = daemon_options;
	    return 0;

	case VINUM_PARITYOP:				    /* check/rebuild RAID-4/5 parity */
	    parityops((struct vinum_ioctl_msg *) data);
	    return 0;

	    /* move an object */
	case VINUM_MOVE:
	    moveobject((struct vinum_ioctl_msg *) data);
	    return 0;

	default:
	    /* FALLTHROUGH */
	    break;
	}

    case VINUM_DRIVE_TYPE:
    default:
	log(LOG_WARNING,
	    "vinumioctl: invalid ioctl from process %d (%s): %lx\n",
	    curthread->td_proc->p_pid,
	    curthread->td_proc->p_comm,
	    cmd);
	return EINVAL;

    case VINUM_SD_TYPE:
    case VINUM_RAWSD_TYPE:
	objno = Sdno(dev);

	sd = &SD[objno];

	switch (cmd) {
      case DIOCGDINFO:				    /* get disk label */
	    get_volume_label(sd->name, 1, sd->sectors, (struct disklabel *) data);
	    break;

	    /*
	     * We don't have this stuff on hardware,
	     * so just pretend to do it so that
	     * utilities don't get upset.
	     */
	case DIOCWDINFO:				    /* write partition info */
	case DIOCSDINFO:				    /* set partition info */
	    return 0;					    /* not a titty */

	default:
	    return ENOTTY;				    /* not my kind of ioctl */
	}

	return 0;					    /* pretend we did it */

    case VINUM_RAWPLEX_TYPE:
    case VINUM_PLEX_TYPE:
	objno = Plexno(dev);

	plex = &PLEX[objno];

	switch (cmd) {
	case DIOCGDINFO:				    /* get disk label */
	    get_volume_label(plex->name, 1, plex->length, (struct disklabel *) data);
	    break;

	    /*
	     * We don't have this stuff on hardware,
	     * so just pretend to do it so that
	     * utilities don't get upset.
	     */
	case DIOCWDINFO:				    /* write partition info */
	case DIOCSDINFO:				    /* set partition info */
	    return 0;					    /* not a titty */

	default:
	    return ENOTTY;				    /* not my kind of ioctl */
	}

	return 0;					    /* pretend we did it */

    case VINUM_VOLUME_TYPE:
	objno = Volno(dev);

	if ((unsigned) objno >= (unsigned) vinum_conf.volumes_allocated) /* not a valid volume */
	    return ENXIO;
	vol = &VOL[objno];
	if (vol->state != volume_up)			    /* not up, */
	    return EIO;					    /* I/O error */

	switch (cmd) {

	case DIOCGMEDIASIZE:
	    *(off_t *)data = vol->size << DEV_BSHIFT;
	    break;

	case DIOCGSECTORSIZE:
	    *(u_int *)data = DEV_BSIZE;
	    break;

	    /*
	     * We don't have this stuff on hardware,
	     * so just pretend to do it so that
	     * utilities don't get upset.
	     */
	case DIOCWDINFO:				    /* write partition info */
	case DIOCSDINFO:				    /* set partition info */
	    return 0;					    /* not a titty */

	case DIOCWLABEL:				    /* set or reset label writeable */
	    if ((flag & FWRITE) == 0)			    /* not writeable? */
		return EACCES;				    /* no, die */
	    if (*(int *) data != 0)			    /* set it? */
		vol->flags |= VF_WLABEL;		    /* yes */
	    else
		vol->flags &= ~VF_WLABEL;		    /* no, reset */
	    break;

	default:
	    return ENOTTY;				    /* not my kind of ioctl */
	}
	break;
    }
    return 0;						    /* XXX */
}
Ejemplo n.º 6
0
void init_oscillator(void) {
  unlock_config();

  // OSCCON
  OSCCONbits.FRCDIV = 0b000; // Internal Fast RC (FRC) Oscillator Clock Divider (FRC divided by 1)
  OSCCONbits.DRMEN = 0;      // Dream Mode Enable (Dream mode is disabled)
  OSCCONbits.SLP2SPD = 0;    // Sleep 2-speed Startup Control (Use the selected clock directly)
  OSCCONbits.CLKLOCK = 0;    // Clock Selection Lock Enable (Clock and PLL selections are not locked and may be modified)
  OSCCONbits.SLPEN = 0;      // Sleep Mode Enable (Device will enter Idle mode when a WAIT instruction is executed)
  OSCCONbits.SOSCEN = 0;      // Secondary Oscillator (SOSC) Enable (Disable Secondary Oscillator)

  // OSCTUN
  OSCTUNbits.TUN = 0b00000; // FRC Oscillator Tuning (Center frequency. Oscillator runs at calibrated frequency (8 MHz))

  // PB1DIV
  while(!PB1DIVbits.PBDIVRDY);
  PB1DIVbits.PBDIV = 0b0000001; // Peripheral Bus 1 Clock Divisor Control (PBCLK1 is SYSCLK divided by 2)

  // PB2DIV
  PB2DIVbits.ON = 1;            // Peripheral Bus 2 Output Clock Enable (Output clock is enabled)
  while(!PB2DIVbits.PBDIVRDY);
  PB2DIVbits.PBDIV = 0b0000001; // Peripheral Bus 2 Clock Divisor Control (PBCLK2 is SYSCLK divided by 2)

  // PB3DIV
  PB3DIVbits.ON = 1;            // Peripheral Bus 3 Output Clock Enable (Output clock is enabled)
  while(!PB3DIVbits.PBDIVRDY);
  PB3DIVbits.PBDIV = 0b0110010; // Peripheral Bus 3 Clock Divisor Control (PBCLK3 is SYSCLK divided by 50)

  // PB4DIV
  PB4DIVbits.ON = 1;            // Peripheral Bus 4 Output Clock Enable (Output clock is enabled)
  while(!PB4DIVbits.PBDIVRDY);
  PB4DIVbits.PBDIV = 0b0000001; // Peripheral Bus 4 Clock Divisor Control (PBCLK4 is SYSCLK divided by 2)

  // PB5DIV
  PB5DIVbits.ON = 1;            // Peripheral Bus 5 Output Clock Enable (Output clock is enabled)
  while(!PB5DIVbits.PBDIVRDY);
  PB5DIVbits.PBDIV = 0b0000001; // Peripheral Bus 5 Clock Divisor Control (PBCLK5 is SYSCLK divided by 2)

  // PB7DIV
  PB7DIVbits.ON = 1;            // Peripheral Bus 7 Output Clock Enable (Output clock is enabled)
  while(!PB7DIVbits.PBDIVRDY);
  PB7DIVbits.PBDIV = 0b0000000; // Peripheral Bus 7 Clock Divisor Control (PBCLK7 is SYSCLK divided by 1)

  // PB8DIV
  PB8DIVbits.ON = 1;            // Peripheral Bus 8 Output Clock Enable (Output clock is enabled)
  while(!PB8DIVbits.PBDIVRDY);
  PB8DIVbits.PBDIV = 0b0000001; // Peripheral Bus 8 Clock Divisor Control (PBCLK8 is SYSCLK divided by 2)

  /**
   * REFO1CLK == (PBCLK1 / (2 * (RODIV + (ROTRIM / 512)))) ==
   * (100Mhz / (2 * (2 + (256/512)))) == (100Mhz / 5) == 20Mhz
   *
   * In other words, REFO1CLK is set up to output at (SYSCLK / 10).
   */

  // Initialize REFCLKO1 PPS pin
  CFGCONbits.IOLOCK = 0;
  TRISFbits.TRISF0 = OUTPUT;
  RPF0R = 0b1111; // Assign REFCLKO1 to RF0
  CFGCONbits.IOLOCK = 1;

  // REFO1CON
  REFO1CONbits.ACTIVE = 0;                // Reference Clock Request Status (Reference clock request is not active)
  REFO1CONbits.ON = 0;                    // Output Enable (Reference Oscillator Module disabled)

  REFO1CONbits.ROSEL = 0b0001;            // Reference Clock Source Select (PBCLK1)
  REFO1CONbits.SIDL = 1;                  // Peripheral Stop in Idle Mode (Discontinue module operation when device enters Idle mode)
  REFO1CONbits.OE = 1;                    // Reference Clock Output Enable (Reference clock is driven out on REFCLKO1 pin)

  REFO1CONbits.DIVSWEN = 1;               // Divider Switch Enable (Divider switch is in progress)
  REFO1CONbits.RODIV = 0b000000000000010; // Reference Clock Divider (Divide by 2)
  REFO1CONbits.DIVSWEN = 0;               // Divider Switch Enable (Divider switch is complete)

  // REFO1TRIM
  REFO1TRIMbits.ROTRIM = 0b100000000;     // Reference Oscillator Trim (256/512 divisor added to RODIV value)

  // Enable REFCLKO1
  REFO1CONbits.ACTIVE = 1;                // Reference Clock Request Status (Reference clock request is active)
  REFO1CONbits.ON = 1;                    // Output Enable (Reference Oscillator Module enabled)

  // REF02CON
  REFO2CONbits.ACTIVE = 0;                // Reference Clock Request Status (Reference clock request is not active)
  REFO2CONbits.ON = 0;                    // Output Enable (Reference Oscillator Module disabled)
  REFO2CONbits.OE = 0;                    // Reference Clock Output Enable (Reference clock is not driven out on REFCLKO2 pin)

  // REF03CON
  REFO3CONbits.ACTIVE = 0;                // Reference Clock Request Status (Reference clock request is not active)
  REFO3CONbits.ON = 0;                    // Output Enable (Reference Oscillator Module disabled)
  REFO3CONbits.OE = 0;                    // Reference Clock Output Enable (Reference clock is not driven out on REFCLKO3 pin)

  // REF04CON
  REFO4CONbits.ACTIVE = 0;                // Reference Clock Request Status (Reference clock request is not active)
  REFO4CONbits.ON = 0;                    // Output Enable (Reference Oscillator Module disabled)
  REFO4CONbits.OE = 0;                    // Reference Clock Output Enable (Reference clock is not driven out on REFCLKO4 pin)

  lock_config();
}
Ejemplo n.º 7
0
void init_peripheral_modules(void) {
  unlock_config();
  CFGCONbits.PMDLOCK = 0;

  /**
   * To disable a module, first set its ON bit (or equivalent) to 0 and then set
   * the appropriate PMD bit to 1 (disabled).
   */

  // ADC
  //TODO: ADC ON bit
  //PMD1bits.ADCMD = 1;

  // Comparator Voltage Reference
  CVRCONbits.ON = 0;
  PMD1bits.CVRMD = 1;

  // Comparator 1
  CM1CONbits.ON = 0;
  PMD2bits.CMP1MD = 1;

  // Comparator 2
  CM2CONbits.ON = 0;
  PMD2bits.CMP2MD = 1;

  // Input Capture 1
  IC1CONbits.ON = 0;
  PMD3bits.IC1MD = 1;

  // Input Capture 2
  IC2CONbits.ON = 0;
  PMD3bits.IC2MD = 1;

  // Input Capture 3
  IC3CONbits.ON = 0;
  PMD3bits.IC3MD = 1;

  // Input Capture 4
  IC4CONbits.ON = 0;
  PMD3bits.IC4MD = 1;

  // Input Capture 5
  IC5CONbits.ON = 0;
  PMD3bits.IC5MD = 1;

  // Input Capture 6
  IC6CONbits.ON = 0;
  PMD3bits.IC6MD = 1;

  // Input Capture 7
  IC7CONbits.ON = 0;
  PMD3bits.IC7MD = 1;

  // Input Capture 8
  IC8CONbits.ON = 0;
  PMD3bits.IC8MD = 1;

  // Input Capture 9
  IC9CONbits.ON = 0;
  PMD3bits.IC9MD = 1;

  // Output Compare 1
  OC1CONbits.ON = 0;
  PMD3bits.OC1MD = 1;

  // Output Compare 2
  OC2CONbits.ON = 0;
  PMD3bits.OC2MD = 1;

  // Output Compare 3
  OC3CONbits.ON = 0;
  PMD3bits.OC3MD = 1;

  // Output Compare 4
  OC4CONbits.ON = 0;
  PMD3bits.OC4MD = 1;

  // Output Compare 5
  OC5CONbits.ON = 0;
  PMD3bits.OC5MD = 1;

  // Output Compare 6
  OC6CONbits.ON = 0;
  PMD3bits.OC6MD = 1;

  // Output Compare 7
  OC7CONbits.ON = 0;
  PMD3bits.OC7MD = 1;

  // Output Compare 8
  OC8CONbits.ON = 0;
  PMD3bits.OC8MD = 1;

  // Output Compare 9
  OC9CONbits.ON = 0;
  PMD3bits.OC9MD = 1;

  // Timer1
  //T1CONbits.ON = 0;
  //PMD4bits.T1MD = 1;

  // Timer2
  T2CONbits.ON = 0;
  PMD4bits.T2MD = 1;

  // Timer3
  T3CONbits.ON = 0;
  PMD4bits.T3MD = 1;

  // Timer4
  T4CONbits.ON = 0;
  PMD4bits.T4MD = 1;

  // Timer5
  T5CONbits.ON = 0;
  PMD4bits.T5MD = 1;

  // Timer6
  T6CONbits.ON = 0;
  PMD4bits.T6MD = 1;

  // Timer7
  T7CONbits.ON = 0;
  PMD4bits.T7MD = 1;

  // Timer8
  T8CONbits.ON = 0;
  PMD4bits.T8MD = 1;

  // Timer9
  T9CONbits.ON = 0;
  PMD4bits.T9MD = 1;

  // UART1
  U1MODEbits.ON = 0;
  PMD5bits.U1MD = 1;

  // UART2
  U2MODEbits.ON = 0;
  PMD5bits.U2MD = 1;

  // UART3
  U3MODEbits.ON = 0;
  PMD5bits.U3MD = 1;

  // UART4
  U4MODEbits.ON = 0;
  PMD5bits.U4MD = 1;

  // UART5
  U5MODEbits.ON = 0;
  PMD5bits.U5MD = 1;

  // UART6
  U6MODEbits.ON = 0;
  PMD5bits.U6MD = 1;

  // SPI1
  //SPI1CONbits.ON = 0;
  //PMD5bits.SPI1MD = 1;

  // SPI2
  SPI2CONbits.ON = 0;
  PMD5bits.SPI2MD = 1;

  // SPI3
  SPI3CONbits.ON = 0;
  PMD5bits.SPI3MD = 1;

  // SPI4
  SPI4CONbits.ON = 0;
  PMD5bits.SPI4MD = 1;

  // SPI5
  SPI5CONbits.ON = 0;
  PMD5bits.SPI5MD = 1;

  // SPI6
  SPI6CONbits.ON = 0;
  PMD5bits.SPI6MD = 1;

  // I2C1
  I2C1CONbits.ON = 0;
  PMD5bits.I2C1MD = 1;

  // I2C3
  I2C3CONbits.ON = 0;
  PMD5bits.I2C3MD = 1;

  // I2C4
  I2C4CONbits.ON = 0;
  PMD5bits.I2C4MD = 1;

  // I2C5
  I2C5CONbits.ON = 0;
  PMD5bits.I2C5MD = 1;

  // USB
  //TODO: USB ON bit
  //PMD5bits.USBMD = 1;

  // CAN 1
  //C1CONbits.ON = 0;
  //PMD5bits.CAN1MD = 1;

  // CAN 2
  C2CONbits.ON = 0;
  PMD5bits.CAN2MD = 1;

  // RTCC
  RTCCONbits.ON = 0;
  PMD6bits.RTCCMD = 1;

  /**
   * Note: Reference clock outputs are not disabled due to an error condition
   * noted in the revision A1 errata.
   */

  // Reference Clock Output 1
  //REFO1CONbits.ON = 0;
  //PMD6bits.REFO1MD = 1;

  // Reference Clock Output 2
  //REFO2CONbits.ON = 0;
  //PMD6bits.REFO2MD = 1;

  // Reference Clock Output 3
  //REFO3CONbits.ON = 0;
  //PMD6bits.REFO3MD = 1;

  // Reference Clock Output 4
  //REFO4CONbits.ON = 0;
  //PMD6bits.REFO4MD = 1;

  // PMP
  PMCONbits.ON = 0;
  PMD6bits.PMPMD = 1;

  // SQI 1
  SQI1CFGbits.SQIEN = 0;
  PMD6bits.SQI1MD = 1;

  // Ethernet
  ETHCON1bits.ON = 0;
  PMD6bits.ETHMD = 1;

  // DMA
  DMACONbits.ON = 0;
  PMD7bits.DMAMD = 1;

  // Random Number Generator
  RNGCONbits.PRNGEN = 0;
  RNGCONbits.TRNGEN = 0;
  PMD7bits.RNGMD = 1;

  // Crypto
  CECONbits.DMAEN = 0;
  PMD7bits.CRYPTMD = 1;

  CFGCONbits.PMDLOCK = 1;
  lock_config();
}
Ejemplo n.º 8
0
/* ioctl routine */
int
vinumioctl(struct dev_ioctl_args *ap)
{
    cdev_t dev = ap->a_head.a_dev;
    u_long cmd = ap->a_cmd;
    caddr_t data = ap->a_data;
    int error;
    unsigned int index;					    /* for transferring config info */
    unsigned int sdno;					    /* for transferring config info */
    unsigned int objno;
    struct volume *vol;
    struct partinfo *dpart;
    int fe;						    /* free list element number */
    struct _ioctl_reply *ioctl_reply;			    /* struct to return */

    error = 0;

    /* First, decide what we're looking at */
    switch (DEVTYPE(dev)) {
    case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */
	ioctl_reply = (struct _ioctl_reply *) data;	    /* save the address to reply to */
	switch (cmd) {
#ifdef VINUMDEBUG
	case VINUM_DEBUG:
	    if (((struct debuginfo *) data)->changeit)	    /* change debug settings */
		debug = (((struct debuginfo *) data)->param);
	    else {
		if (debug & DEBUG_REMOTEGDB)
		    boothowto |= RB_GDB;		    /* serial debug line */
		else
		    boothowto &= ~RB_GDB;		    /* local ddb */
		Debugger("vinum debug");
	    }
	    ioctl_reply = (struct _ioctl_reply *) data;	    /* reinstate the address to reply to */
	    ioctl_reply->error = 0;
	    break;
#endif

	case VINUM_CREATE:				    /* create a vinum object */
	    error = lock_config();			    /* get the config for us alone */
	    if (error)					    /* can't do it, */
		break;
	    error = setjmp(command_fail);		    /* come back here on error */
	    if (error == 0)				    /* first time, */
		ioctl_reply->error = parse_user_config((char *) data, /* update the config */
		    &keyword_set);
	    else if (ioctl_reply->error == 0) {		    /* longjmp, but no error status */
		error = 0;
		ioctl_reply->error = EINVAL;		    /* note that something's up */
		ioctl_reply->msg[0] = '\0';		    /* no message? */
	    }
	    unlock_config();
	    break;

	case VINUM_GETCONFIG:				    /* get the configuration information */
	    bcopy(&vinum_conf, data, sizeof(vinum_conf));
	    break;

	    /* start configuring the subsystem */
	case VINUM_STARTCONFIG:
	    error = start_config(*(int *) data);	    /* just lock it.  Parameter is 'force' */
	    break;

	case VINUM_DRIVECONFIG:
	    /*
	     * Move the individual parts of the config to user space.
	     *
	     * Specify the index of the object in the first word of data,
	     * and return the object there
	     */
	    index = *(int *) data;
	    if (index >= (unsigned)vinum_conf.drives_allocated) {
		error = ENXIO;
	    } else {
		bcopy(&DRIVE[index], data, sizeof(struct drive));
	    }
	    break;

	case VINUM_SDCONFIG:
	    index = *(int *) data;
	    if (index >= (unsigned) vinum_conf.subdisks_allocated) {
		error = ENXIO;
	    } else {
		bcopy(&SD[index], data, sizeof(struct sd));
	    }
	    break;

	case VINUM_PLEXCONFIG:
	    index = *(int *) data;
	    if (index >= (unsigned) vinum_conf.plexes_allocated) {
		error = ENXIO;
	    } else {
		bcopy(&PLEX[index], data, sizeof(struct plex));
	    }
	    break;

	case VINUM_VOLCONFIG:
	    index = *(int *) data;
	    if (index >= (unsigned) vinum_conf.volumes_allocated) {
		error = ENXIO;
	    } else {
		bcopy(&VOL[index], data, sizeof(struct volume));
	    }
	    break;

	case VINUM_PLEXSDCONFIG:
	    index = ((int *)data)[0];			    /* get the plex index */
	    sdno = ((int *)data)[1];			    /* and the sd index */
	    if ((index >= (unsigned) vinum_conf.plexes_allocated)
		||(sdno >= PLEX[index].subdisks)) {
		error = ENXIO;
	    } else {
		bcopy(&SD[PLEX[index].sdnos[sdno]], data, sizeof(struct sd));
	    }
	    break;
	case VINUM_SAVECONFIG:
	    /*
	     * We get called in two places: one from the
	     * userland config routines, which call us
	     * to complete the config and save it.  This
	     * call supplies the value 0 as a parameter.
	     *
	     * The other place is from the user "saveconfig"
	     * routine, which can only work if we're *not*
	     * configuring.  In this case, supply parameter 1.
	     */
	    if (VFLAGS & VF_CONFIGURING) {		    /* must be us, the others are asleep */
		if (*(int *) data == 0)			    /* finish config */
		    finish_config(1);			    /* finish the configuration and update it */
		else
		    error = EBUSY;
	    }
	    if (error == 0)
		save_config();				    /* save configuration to disk */
	    break;

	case VINUM_RELEASECONFIG:			    /* release the config */
	    if (VFLAGS & VF_CONFIGURING) {		    /* must be us, the others are asleep */
		finish_config(0);			    /* finish the configuration, don't change it */
		save_config();				    /* save configuration to disk */
	    } else {
		error = EINVAL;				    /* release what config? */
	    }
	    break;

	case VINUM_INIT:
	    ioctl_reply = (struct _ioctl_reply *) data;	    /* reinstate the address to reply to */
	    ioctl_reply->error = 0;
	    break;

	case VINUM_RESETCONFIG:
	    if (vinum_inactive(0)) {			    /* if the volumes are not active */
		/*
		 * Note the open count.  We may be called from v, so we'll be open.
		 * Keep the count so we don't underflow
		 */
		free_vinum(1);				    /* clean up everything */
		log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");
		ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
		ioctl_reply->error = 0;
	    } else {
		error = EBUSY;
	    }

	case VINUM_SETSTATE:
	    setstate((struct vinum_ioctl_msg *) data);	    /* set an object state */
	    break;

	    /*
	     * Set state by force, without changing
	     * anything else.
	     */
	case VINUM_SETSTATE_FORCE:
	    setstate_by_force((struct vinum_ioctl_msg *) data);	/* set an object state */
	    break;

#ifdef VINUMDEBUG
	case VINUM_MEMINFO:
	    vinum_meminfo(data);
	    break;

	case VINUM_MALLOCINFO:
	    error = vinum_mallocinfo(data);
	    break;

	case VINUM_RQINFO:
	    error = vinum_rqinfo(data);
	    break;
#endif

	case VINUM_REMOVE:
	    remove((struct vinum_ioctl_msg *) data);	    /* remove an object */
	    break;

	case VINUM_GETFREELIST:				    /* get a drive free list element */
	    index = *(int *) data;			    /* get the drive index */
	    fe = ((int *) data)[1];			    /* and the free list element */
	    if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */
		||(DRIVE[index].state == drive_unallocated)) {
		error = ENODEV;
	    } else if (fe >= DRIVE[index].freelist_entries) {
		error = ENOENT;
	    } else {
		bcopy(&DRIVE[index].freelist[fe], data,
		      sizeof(struct drive_freelist));
	    }
	    break;

	case VINUM_RESETSTATS:
	    resetstats((struct vinum_ioctl_msg *) data);    /* reset object stats */
	    break;

	    /* attach an object to a superordinate object */
	case VINUM_ATTACH:
	    attachobject((struct vinum_ioctl_msg *) data);
	    break;

	    /* detach an object from a superordinate object */
	case VINUM_DETACH:
	    detachobject((struct vinum_ioctl_msg *) data);
	    break;

	    /* rename an object */
	case VINUM_RENAME:
	    renameobject((struct vinum_rename_msg *) data);
	    break;

	    /* replace an object */
	case VINUM_REPLACE:
	    replaceobject((struct vinum_ioctl_msg *) data);
	    break;

	case VINUM_DAEMON:
	    vinum_daemon();				    /* perform the daemon */
	    break;

	case VINUM_FINDDAEMON:				    /* check for presence of daemon */
	    error = vinum_finddaemon();
	    break;

	case VINUM_SETDAEMON:				    /* set daemon flags */
	    error = vinum_setdaemonopts(*(int *) data);
	    break;

	case VINUM_GETDAEMON:				    /* get daemon flags */
	    *(int *) data = daemon_options;
	    break;

	case VINUM_PARITYOP:				    /* check/rebuild RAID-4/5 parity */
	    parityops((struct vinum_ioctl_msg *) data);
	    break;

	    /* move an object */
	case VINUM_MOVE:
	    moveobject((struct vinum_ioctl_msg *) data);
	    break;
	default:
	    error = EINVAL;
	    break;
	}
	break;
    case VINUM_LABEL:
    case VINUM_DRIVE_TYPE:
    case VINUM_SD_TYPE:
    case VINUM_RAWSD_TYPE:
    case VINUM_RAWPLEX_TYPE:
    case VINUM_PLEX_TYPE:
	error = EINVAL;
	break;
    case VINUM_VOLUME_TYPE:
	objno = Volno(dev);

	if ((unsigned)objno >= (unsigned)vinum_conf.volumes_allocated) {
	    error = ENXIO;
	    break;
	}
	vol = &VOL[objno];
	if (vol->state != volume_up) {
	    error = EIO;
	    break;
	}

	switch(cmd) {
	case DIOCGPART:
	    dpart = (void *)data;

	    bzero(dpart, sizeof(*dpart));
	    dpart->media_offset  = 0;
	    dpart->media_size    = (u_int64_t)vol->size * DEV_BSIZE;
	    dpart->media_blocks  = vol->size;
	    dpart->media_blksize = DEV_BSIZE;
	    dpart->fstype = FS_BSDFFS;
	    break;
	default:
	    error = EINVAL;
	}
	break;
    default:
	error = EINVAL;
	break;
    }
    if (error) {
	log(LOG_WARNING,
	    "vinumioctl: invalid ioctl from process %d (%s): %lx\n",
	    curproc->p_pid,
	    curproc->p_comm,
	    cmd);
    }
    return error;
}