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

📄 sdo.c

📁 AVR平台下的CanOpen协议桟源码包括应用
💻 C
📖 第 1 页 / 共 4 页
字号:
	      if( nbytes <= 1 )
		{
		  if( spi_set_holdtime( msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      break;
	    case 2:
	      if( nbytes <= 1 )
		{
		  if( spi_set_rising_clk( msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      break;
	    default:
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	      break;
	    }
	  break;

	default:
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	  break;
	}
      break;

#ifdef __2313_SLAVE_PRESENT__
    case OD_PROGRAM_CODE_HI:
      if( od_index_lo == OD_PROGRAM_CODE_LO )
	{
	  if( od_subind == 1 )
	    {
	      if( nbytes == 4 || nbytes == 0 )
		{
		  if( do_serial_instruction( &msg_data[4] ) == FALSE )
		    {
		      /* Something wrong with parameters */
		      sdo_error = SDO_ECODE_ATTRIBUTE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	}
      break;
#endif /* __2313_SLAVE_PRESENT__ */

    case OD_SWITCH_TO_LOADER_HI:
      if( od_index_lo == OD_SWITCH_TO_LOADER_LO )
	{
	  if( od_subind == 0 )
	    {
	      if( nbytes <= 1 )
		{
#ifdef __2313_SLAVE_PRESENT__
		  /* Disable Timer1 interrupt to stop
		     the Slave aliveness-check mechanism:
		     Slave should take control of the node,
		     after some time, unless.... */
		  timer1_stop();
#endif /* __2313_SLAVE_PRESENT__ */

		  /* Send a reply before making the jump... */
		  msg_data[0] = SDO_INITIATE_DOWNLOAD_RESP;
		  msg_data[4] = 0;
		  can_write( C91_SDOTX, C91_SDOTX_LEN, msg_data );
		  timer2_delay_ms( 5 );

		  /* ...there is a Bootloader: it will take control
		     (and also keep the Slave happy, if present) */
		  jump_to_bootloader();
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	}
      break;

    case OD_DEVICE_INFO_HI:
      switch( od_index_lo )
	{
	case OD_LIFETIME_FACTOR_LO:
	  if( od_subind == 0 )
	    {
	      if( nbytes <= 1 )
		{
		  /* Set new Life Time Factor */
		  if( guarding_set_lifetime( msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	  break;

	case OD_STORE_PARAMETERS_LO:
	  if( od_subind >= 1 && od_subind <= OD_STORE_MAX_SUBID )
	    {
	      if( nbytes == 4 || nbytes == 0 )
		{
		  /* Check for correct signature */
		  if( msg_data[4] == 's' && msg_data[5] == 'a' &&
		      msg_data[6] == 'v' && msg_data[7] == 'e' )
		    {
		      if( store_save_parameters( od_subind ) == FALSE )
			{
			  /* Something went wrong */
			  sdo_error = SDO_ECODE_HARDWARE;
			}
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	  break;

	case OD_DFLT_PARAMETERS_LO:
	  if( od_subind >= 1 && od_subind <= OD_STORE_MAX_SUBID )
	    {
	      if( nbytes == 4 || nbytes == 0 )
		{
		  /* Check for correct signature */
		  if( msg_data[4] == 'l' && msg_data[5] == 'o' &&
		      msg_data[6] == 'a' && msg_data[7] == 'd' )
		    {
		      if( store_set_defaults( od_subind ) == FALSE )
			{
			  /* Something went wrong */
			  sdo_error = SDO_ECODE_HARDWARE;
			}
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	  break;

	case OD_HEARTBEAT_TIME_LO:
	  if( od_subind == 0 )
	    {
	      if( nbytes == 2 || nbytes == 0 )
		{
		  /* Set new Heartbeat Time */
		  if( guarding_set_heartbeattime( &msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	  break;

	default:
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	  break;
	}
      break;

    case OD_CAN_CONFIG_HI:
      if( od_index_lo == OD_CAN_CONFIG_LO )
	{
	  switch( od_subind )
	    {
	    case 1:
	      if( nbytes <= 1 )
		{
		  if( can_set_rtr_disabled( msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		/* Wrong number of bytes provided */
		sdo_error = SDO_ECODE_ATTRIBUTE;
	      break;
	    case 2:
	      if( nbytes <= 1 )
		{
		  if( can_set_opstate_init( msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		/* Wrong number of bytes provided */
		sdo_error = SDO_ECODE_ATTRIBUTE;
	      break;
	    case 3:
	      if( nbytes <= 1 )
		{
		  if( can_set_busoff_maxcnt( msg_data[4] ) == FALSE )
		    sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	      else
		/* Wrong number of bytes provided */
		sdo_error = SDO_ECODE_ATTRIBUTE;
	      break;
	    default:
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	      break;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	  break;
	}
      break;

    case OD_ADC_CALIB_RANGE_HI:
      if( od_index_lo == OD_ADC_CALIB_RANGE_LO )
	{
	  /* There are six voltage ranges on this ADC */
	  if( od_subind != 0 && od_subind <= STORE_ADC_CALIB_BLOCKS )
	    {
	      if( nbytes == 4 || nbytes == 0 )
		{
		  if( adc_calibrate_range( od_subind-1 ) == FALSE )
		    {
		      /* Reset or self-calibrate operation failed */
		      sdo_error = SDO_ECODE_HARDWARE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	}
      break;

    case OD_ADC_CALIB_PARS_HI:
      if( od_index_lo < STORE_ADC_CALIB_BLOCKS )
	{
	  /* Check for valid parameters */
	  if( od_subind != 0 && od_subind <= STORE_ADC_CALIB_PARS )
	    {
	      if( nbytes == 4 || nbytes == 0 )
		{
		  if( adc_set_calib_const( od_index_lo, od_subind-1,
					   &msg_data[4] ) == FALSE )
		    {
		      /* Something went wrong while writing to EEPROM */
		      sdo_error = SDO_ECODE_HARDWARE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	}
      break;

    case OD_ADC_CALIB_ERASE_HI:
      if( od_index_lo < STORE_ADC_CALIB_BLOCKS )
	{
	  /* Check for valid parameters */
	  if( od_subind == 0 )
	    {
	      if( nbytes <= 1 )
		{
		  if( adc_erase_calib_const( od_index_lo,
					     msg_data[4] ) == FALSE )
		    {
		      /* Something went wrong while writing to EEPROM */
		      sdo_error = SDO_ECODE_HARDWARE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	}
      break;

    case OD_ADC_CALIB_WR_ENA_HI:
      if( od_index_lo == OD_ADC_CALIB_WR_ENA_LO )
	{
	  if( od_subind == 0 )
	    {
	      if( nbytes <= 1 )
		{
		  if( adc_calib_const_write_enable( msg_data[4] ) == FALSE )
		    {
		      /* Something wrong with parameters */
		      sdo_error = SDO_ECODE_ATTRIBUTE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	}
      else
	{
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	}
      break;

    case OD_ELMB_SERIAL_NO_HI:
      switch( od_index_lo )
	{
	case OD_ELMB_SERIAL_NO_LO:
	  if( od_subind == 0 )
	    {
	      if( nbytes == 4 || nbytes == 0 )
		{
		  /* Set the ELMB Serial Number */
		  if( sn_set_serial_number( &msg_data[4] ) == FALSE )
		    {
		      /* Something went wrong */
		      sdo_error = SDO_ECODE_HARDWARE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	  break;

	case OD_ELMB_SN_WRITE_ENA_LO:
	  if( od_subind == 0 )
	    {
	      if( nbytes <= 1 )
		{
		  /* Enable a write-operation to the ELMB Serial Number */
		  if( sn_serial_number_write_enable( msg_data[4] ) == FALSE )
		    {
		      /* Something wrong with parameters */
		      sdo_error = SDO_ECODE_ATTRIBUTE;
		    }
		}
	      else
		{
		  /* Wrong number of bytes provided */
		  sdo_error = SDO_ECODE_ATTRIBUTE;
		}
	    }
	  else
	    {
	      /* The sub-index does not exist */
	      sdo_error = SDO_ECODE_ATTRIBUTE;
	    }
	  break;

	default:
	  /* The index can not be accessed, does not exist */
	  sdo_error = SDO_ECODE_NONEXISTENT;
	  break;
	}
      break;

    default:
      /* The index can not be accessed, does not exist */
      sdo_error = SDO_ECODE_NONEXISTENT;
      break;
    }

  /* Set appropriate SDO command specifier for reply */
  msg_data[0] = SDO_INITIATE_DOWNLOAD_RESP;

  /* CANopen: bytes 4 to 7 reserved, so set to zero, except when programming
     the Slave: the SDO reply possibly contains a read memory byte... */
  if( od_index_hi != OD_PROGRAM_CODE_HI )
    {
      msg_data[4] = 0;
      msg_data[5] = 0;
      msg_data[6] = 0;
      msg_data[7] = 0;
    }

  return sdo_error;
}

/* ------------------------------------------------------------------------ */

static void sdo_abort( BYTE error_class,
		       BYTE error_code,
		       BYTE *msg_data )
{
  msg_data[0] = SDO_ABORT_TRANSFER;

  /* msg_data[1], msg_data[2], msg_data[3] should contain
     index and sub-index: leave intact */

  /* Error class */
  msg_data[7] = error_class;

  /* Error code */
  msg_data[6] = error_code;

  /* Additional code, not filled in for the time being */
  msg_data[5] = 0;
  msg_data[4] = 0;

  can_write( C91_SDOTX, C91_SDOTX_LEN, msg_data );
}

/* ------------------------------------------------------------------------ */
/* Function call which results in a jump to address 0xF000
   which starts the Bootloader program
   (provided the Bootloader size is set (by the fuses) to 4 kWords!) */

static void jump_to_bootloader( void )
{
#ifndef __ELMB103__
  BYTE flashbyte;

  /* Set (byte) address in the proper registers (for ELPM access) */
  asm( "ldi R30,0x00" );
  asm( "ldi R31,0xE0" );

  /* Set RAMPZ register to access the upper 64k page of program memory */
  RAMPZ = 1;

  /* Read the program memory byte and store it in 'flashbyte' */
  asm( "elpm" );
  asm( "mov %flashbyte, R0" );

  /* Reset RAMPZ register */
  RAMPZ = 0;

  /* If there is no Bootloader, return to the user application ! */
  if( flashbyte == 0xFF )
    {
      /* CANopen Error Code 0x6000: device software */
      can_write_emergency( 0x00, 0x50, EMG_NO_BOOTLOADER,
			   0, 0, 0, ERRREG_MANUFACTURER );
      return;
    }
  
  /* Disable watchdog timer (if possible) */
  watchdog_disable();

  /* Disable all interrupts */
  CLI();

  /* Z-pointer: 0xF000 (word address) */
  asm( "ldi R30,0x00" );
  asm( "ldi R31,0xF0" );
  
  /* Jump to the Bootloader at (word) address 0xF000 */
  asm( "ijmp" );
#endif /* __ELMB103__ */
}

/* ------------------------------------------------------------------------ */

⌨️ 快捷键说明

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