Esempio n. 1
0
// Set a new PWM value for a given pin
// Primarily this consists of updating the PWMValue and then 
// re-sorting the list of active pins by removing and then adding
// the pin to the linked list.
int32_t SoftPWMServoRawWrite(uint32_t Pin, uint32_t Value, bool PinType)
{
    int i;
    int32_t intr;

    // Insert our ISR handler, if it's not already there
    if (!Initalized)
    {
        SoftPWMServoInit();
    }

    // Limit check the inputs
    if (Value > FrameTime)
    {
        Value = FrameTime;
    }
    if (Pin > SOFTPWMSERVO_MAX_PINS)
    {
        return SOFTPWMSERVO_ERROR;
    }
    
    // And if this pin already has this PWM Value, then don't do anything.
    if (Value == Chan[ActiveBuffer][Pin].PWMValue)
    {
        return SOFTPWMSERVO_OK;
    }

    // The easy way to prevent the ISR from doing a buffer swap while
    // we're in the middle of this is to disable interrupts during 
    // the time that we're mucking with the list.
    // TODO: Switch to using 3 buffers - one 'active' that the ISR
    // is currently using, one 'primed' that the mainline code doesn't
    // touch but has updates and is ready to be swapped before the
    // next rising edge, and then 'inactive' which is the one we modify
    // with here. Maybe we wouldn't need to disable interrupts then.
    intr = disableInterrupts();

    // If needed, copy the values from the previously active buffer
    // into the inactive buffer before we begin work on it.
    CopyBuffers();
 
    // Always make sure this pin's enabled
    SoftPWMServoPinEnable(Pin, PinType);

    // Update the PWM value for this pin
    Chan[InactiveBuffer][Pin].PWMValue = Value;
    Chan[InactiveBuffer][Pin].IsServo = PinType;
    
    // Remove it from the list
    Remove(Pin);
    
    // And add it back in the list, in the right place (in time)
    Add(Pin);    

    restoreInterrupts(intr);  

    return SOFTPWMSERVO_OK;
}
Esempio n. 2
0
// Disable the SoftPWM functionality on a particular pin number
int32_t SoftPWMServoPinDisable(uint32_t Pin)
{
    int32_t intr;
    intr = disableInterrupts();
    CopyBuffers();
    
    // Pull this one out of the linked list of active channels
    Remove(Pin);

    // Mark it as unused
    Chan[InactiveBuffer][Pin].SetPort = NULL;
    Chan[InactiveBuffer][Pin].ClearPort = NULL;
    restoreInterrupts(intr);    

    return SOFTPWMSERVO_OK;
}
Esempio n. 3
0
int mme_user_send_command (mme_user_t *instance, void *arg)
{
	int res = 0;
        MME_ERROR status = MME_INTERNAL_ERROR;

	MME_TransformerHandle_t handle;
	mme_send_command_t     *sendCommand = (mme_send_command_t *)arg;

	mme_user_command_t     *intCommand;
	MME_Command_t*          command;

	mme_user_trans_t       *trans;
	int                     type, cpuNum, ver, idx;

	/* Allocate an internal Command desc */
	_ICS_OS_ZALLOC(intCommand, sizeof(*intCommand));
	if (intCommand == NULL) {
		status = MME_NOMEM;
		res = -ENOMEM;
		goto exit;
	}
	
	/* Get address of embedded MME_Command_t */
	command = &intCommand->command;

	/* Bugzilla 4956 
	 * We set the reference count of this data structure to 2 so that it
	 * will not be freed by on completion until we have done the
	 * copy_to_user() below
	 */
	atomic_set(&intCommand->refCount, 2);

	INIT_LIST_HEAD(&intCommand->list);

	/* Copy in transformer handle and CommandInfo from userspace */
	if (get_user(handle, &(sendCommand->handle)) ||
	    get_user(intCommand->userCommand, &(sendCommand->command)) || 
	    copy_from_user(command, intCommand->userCommand, sizeof(*command))) {
		res = -EFAULT;
		goto errorFreeCmd;
	}

	/* Decode the supplied transformer handle */
	_MME_DECODE_HDL(handle, type, cpuNum, ver, idx);

	if (handle == 0 || type != _MME_TYPE_TRANSFORMER || idx >= _MME_TRANSFORMER_INSTANCES) {
		res = -EINVAL;
		status = MME_INVALID_HANDLE;
		goto errorFreeCmd;
	}

	/* Get a handle into the local transformer table */
	trans = instance->insTrans[idx];
	
	if (trans == NULL) {
		res = -EINVAL;
		status = MME_INVALID_HANDLE;
		goto errorFreeCmd;
	}

	if (sizeof(MME_Command_t) != command->StructSize) {
		res = -EINVAL;
		status = MME_INVALID_HANDLE;
		goto errorFreeCmd;
	}

        /* Allocate kernel mem for the user private data and copy across */
	if (command->Param_p && command->ParamSize) {
                void* userParam_p = command->Param_p;
		command->Param_p = _ICS_OS_MALLOC(command->ParamSize);

		if (NULL == command->Param_p) {
			status = MME_NOMEM;
			res = -ENOMEM;
			goto errorFreeCmd;
		}
		if (copy_from_user(command->Param_p, userParam_p, 
				   command->ParamSize)) {
			res = -EFAULT;
			goto errorFreeParam;
                }
       	}

        /* Allocate kernel mem for the AddionalInfo data and copy across */
	if (command->CmdStatus.AdditionalInfo_p && command->CmdStatus.AdditionalInfoSize) {
                /* Need the user address to copy back when the command completes */
                intCommand->userAdditionalInfo = command->CmdStatus.AdditionalInfo_p;
		command->CmdStatus.AdditionalInfo_p = _ICS_OS_MALLOC(command->CmdStatus.AdditionalInfoSize);

		if (NULL == command->CmdStatus.AdditionalInfo_p) {
			status = MME_NOMEM;
			res = -ENOMEM;
			goto errorFreeParam;
		}
		if (copy_from_user(command->CmdStatus.AdditionalInfo_p, intCommand->userAdditionalInfo, 
				   command->CmdStatus.AdditionalInfoSize)) {
			res = -EFAULT;
			goto errorFree;
                }
       	}

	/* Copy in all the data buffer information from userspace */
	res = CopyBuffers(command);

	if (0 != res) {
                if (-ENOMEM == res) {
        	        status = MME_NOMEM;
                } 
		goto errorFree;
	}

	/*
	 * Unless we are using MME_WaitCommand() then we require
	 * the internal Command callback to occur (mme_user_help_callback)
	 */
	if (command->CmdEnd != MME_COMMAND_END_RETURN_WAKE)
		command->CmdEnd = MME_COMMAND_END_RETURN_NOTIFY;
	
	/* Call the MME api */
	status = MME_SendCommand(handle, command);
        if (MME_SUCCESS != status) {
                goto errorFree;
        }

	/* Copy the command status structure back - contains command id, state etc */
	if (copy_to_user(&(intCommand->userCommand->CmdStatus), 
                         &(command->CmdStatus), 
			 offsetof(MME_CommandStatus_t, AdditionalInfo_p))) { /* Yuk - need to improve this */
		res = -EFAULT;
        }

	_ICS_OS_MUTEX_TAKE(&instance->ulock);

	/* Add to list of currently executing commands */
	list_add_tail(&intCommand->list, &trans->issuedCmds);

	_ICS_OS_MUTEX_RELEASE(&instance->ulock);

	/* Now call command_free which will 
	 * only free the structure when the refCount hits 0
	 * Command completion will also call it and the winner will
	 * free off the memory
	 */
	mme_user_command_free(instance, intCommand);

        goto exit;

errorFree:
	if (command->CmdStatus.AdditionalInfo_p && command->CmdStatus.AdditionalInfoSize) {
		_ICS_OS_FREE(command->CmdStatus.AdditionalInfo_p);
        }

errorFreeParam:
 	if (command->Param_p && command->ParamSize) {
		_ICS_OS_FREE(command->Param_p);
        }

errorFreeCmd:
        _ICS_OS_FREE(intCommand);

exit:
	/* Write back MME status to caller */
	if (put_user(status, &(sendCommand->status))) {
		res = -EFAULT;
	}

	return res;
}