COUNT SerialRead(char * buf, COUNT len) { COUNT read = 0; COUNT readGeneration; BOOL wasFull = FALSE; do { IsrDisable(IRQ_LEVEL_SERIAL_READ); if ( RingBufferIsFull( &SerialInputRing ) ) { wasFull = TRUE; } read = RingBufferRead(buf, len, &SerialInputRing); readGeneration = ReadGenerationCount; IsrEnable(IRQ_LEVEL_SERIAL_READ); if (read == 0) { GenerationWait(&ReadGeneration, readGeneration, NULL); } } while (read == 0); // We were full, so lets make sure there wasn't any data buffered // in the hal. if ( wasFull ) { HalRaiseInterrupt( IRQ_LEVEL_SERIAL_READ ); } return read; }
/** \brief a initialized packet * * \warning Use *only* at init, not at packet runtime */ void PacketPoolStorePacket(Packet *p) { if (RingBufferIsFull(ringbuffer)) { exit(1); } RingBufferMrMwPut(ringbuffer, (void *)p); SCLogDebug("buffersize %u", RingBufferSize(ringbuffer)); }
COUNT RingBufferWrite( char * buff, COUNT size, struct RING_BUFFER * ring ) { COUNT write = 0; while( write < size && !RingBufferIsFull( ring ) ) { write += RingBufferWriteSmall( buff+write, size-write, ring ); ring->Empty = FALSE; } return write; }
/** \brief a initialized packet * * \warning Use *only* at init, not at packet runtime */ void PacketPoolStorePacket(Packet *p) { if (RingBufferIsFull(ringbuffer)) { exit(1); } /* Clear the PKT_ALLOC flag, since that indicates to push back * onto the ring buffer. */ p->flags &= ~PKT_ALLOC; p->ReleasePacket = PacketPoolReturnPacket; PacketPoolReturnPacket(p); SCLogDebug("buffersize %u", RingBufferSize(ringbuffer)); }
COUNT PipeReadInner( char * buff, COUNT size, PIPE_READ pipe ) { BOOL wasFull; BOOL dataLeft; COUNT read; //Acquire EmptyLock - No readers can progress until there is data. SemaphoreDown( & pipe->EmptyLock, NULL ); //Acqure mutex lock - No one can do any io until //we leave the buffer. SemaphoreDown( & pipe->Mutex, NULL ); //Check and see if the buffer is full. //If it is, then the FullLock should //have been leaked, and writers should be blocking. wasFull = RingBufferIsFull( & pipe->Ring ); ASSERT( wasFull ? (pipe->FullLock.Count == 0) : TRUE ); //Perform the read. read = RingBufferRead( buff, size, & pipe->Ring ); // Ring is protected by a read lock which should prevent zero length reads. ASSERT( read > 0 ); //See if the ring buffer is empty. //If it is then we need to leak the reader lock. dataLeft = !RingBufferIsEmpty( & pipe->Ring ); //Release mutex lock - We are out of the ring, so //let other IO go if its already passed. SemaphoreUp( & pipe->Mutex ); //If the ring was full while we have exclusive access, //and we freed up some space then we should release //the writer lock so writers can go. if( wasFull && read > 0 ) { SemaphoreUp( & pipe->FullLock ); } //If there is data left in the buffer, release the //empty lock so that other readers can go. //If there is no data in the buffer, we cant let //readers progress, so we leak the lock. if( dataLeft ) { SemaphoreUp( & pipe->EmptyLock ); } return read; }
COUNT PipeWriteInner( char * buff, COUNT size, PIPE_WRITE pipe ) { BOOL wasEmpty; BOOL spaceLeft; COUNT write; //Acquire FullLock - No writers can progress until we are done. SemaphoreDown( & pipe->FullLock, NULL ); //Acqure mutex lock - No one can do any io until //we leave the buffer. SemaphoreDown( & pipe->Mutex, NULL ); //Check and see if the buffer is empty. //If it is, then the EmptyLock should //have been leaked, and readers should be blocking. wasEmpty = RingBufferIsEmpty( & pipe->Ring ); ASSERT( wasEmpty ? (pipe->EmptyLock.Count == 0) : TRUE ); //Perform the write. write = RingBufferWrite( buff, size, & pipe->Ring ); // Ring is protected by a write lock which should prevent zero length writes. ASSERT( write > 0 ); //See if the ring buffer is empty. //If it is then we need to leak the reader lock. spaceLeft = !RingBufferIsFull( & pipe->Ring ); //Release mutex lock - We are out of the ring, so //let other IO go if its already passed. SemaphoreUp( & pipe->Mutex ); //If the ring was empty while we have exclusive access, //and we wrote some data, then we should release //the EmptyLock so readers can go. if( wasEmpty && write > 0 ) { SemaphoreUp( & pipe->EmptyLock ); } //If there is space left in the buffer, release the //FullLock so that other writers can go. //If there is no space in the buffer, we cant let //writers progress, so we leak the lock. if( spaceLeft ) { SemaphoreUp( & pipe->FullLock ); } return write; }
void GetBytesInterrupt(void) { while (!RingBufferIsFull(&SerialInputRing)) { char data; if (HalSerialGetChar(&data)) { ASSUME(RingBufferWrite(&data, sizeof(data), &SerialInputRing), 1); } else { break; } } if ( HandlerIsFinished(&ReadGenerationCritObject) ) { GenerationUpdateSafe( &ReadGeneration, ++ReadGenerationCount, &ReadGenerationContext, &ReadGenerationCritObject); } }
int main(void) { InitClock(); SerialInit(); RingBufferInit(&location_buffer, 4, locations); PORTC.DIRSET = 0xF3; PORTE.DIRSET = 0xFF; PORTD.DIRSET = 0x33; PORTB.DIRCLR = 0xFF; /* PortB all inputs */ /* Timers */ //x_axis.step_timer = &TCC1; x_axis.pwm_timer = &TCC0; /* Limit Switches */ x_axis.limit_switch_port = &PORTB; x_axis.limit_switch_mask = (1<<0); /* PORTB.0 */ /* DIR ports (for inverting the stepper motor driver polarity) */ x_axis.sign_select_port = &PORTC; x_axis.sign_switch_mask1 = 0x20; /* PORTC.5 */ x_axis.sign_switch_mask2 = 0x10; /* PORTC.4 */ /* PWM outputs: outputs will be 90 degrees out of phase */ x_axis.phase_pwm_cmp1 = &(TCC0.CCB); x_axis.phase_pwm_cmp2 = &(TCC0.CCA); x_axis.compare_mask = TC0_CCBEN_bm | TC0_CCAEN_bm; /* Power Controls change the period: a longer period means longer off time and lower duty cycle */ //x_axis.axis_idle_power = 60; x_axis.axis_run_power = 31; /* The minimum period of the PWM update timer/counter */ /* Stepper motor tick period = 32 * min_period / 16000000 */ //x_axis.min_period = 15; AxisInit (&x_axis); //y_axis.step_timer = &TCD1; y_axis.pwm_timer = &TCD0; y_axis.limit_switch_port = &PORTB; y_axis.limit_switch_mask = (1<<1); /* PORTB.1 */ y_axis.sign_select_port = &PORTD; y_axis.sign_switch_mask1 = 0x20; y_axis.sign_switch_mask2 = 0x10; y_axis.phase_pwm_cmp1 = &(TCD0.CCB); y_axis.phase_pwm_cmp2 = &(TCD0.CCA); y_axis.compare_mask = TC0_CCBEN_bm | TC0_CCAEN_bm; //y_axis.axis_idle_power = 60; y_axis.axis_run_power = 31; //y_axis.min_period = 15; AxisInit (&y_axis); //z_axis.step_timer = &TCE1; z_axis.pwm_timer = &TCE0; z_axis.limit_switch_port = &PORTB; z_axis.limit_switch_mask = (1<<2); /* PORTB.2 */ z_axis.sign_select_port = &PORTE; z_axis.sign_switch_mask1 = 0x20; /* PORTE.5 */ z_axis.sign_switch_mask2 = 0x10; /* PORTE.4 */ z_axis.phase_pwm_cmp1 = &(TCE0.CCD); z_axis.phase_pwm_cmp2 = &(TCE0.CCC); z_axis.compare_mask = TC0_CCDEN_bm | TC0_CCCEN_bm; //z_axis.axis_idle_power = 60; z_axis.axis_run_power = 31; /* 33 unique waveform values: 0 (ground) to 33 (3.3v) */ //z_axis.min_period = 15; AxisInit (&z_axis); PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; // Fire up the timer for incrementing/decrementing steps TC0_t * step_timer = &TCC1; step_timer->CTRLB = TC_WGMODE_SS_gc; /* Overflow every 1 ms: 16Mhz / (64 * 250) = 1ms */ step_timer->PER = 250; step_timer->CTRLA = TC_CLKSEL_DIV64_gc; step_timer->CTRLFSET = TC_CMD_RESTART_gc; /* Enable the step overflow interrupt */ step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // To Disable: axis->step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; char task = 0; sei(); while(1) { //PORTE.OUTTGL = 0x02; //_delay_ms (10); //SerialData * s = SerialDataTransmitStruct(); //if (s != 0) //{ // s->transmit_data[0] = 'a'; // s->transmit_data[1] = 'b'; // s->transmit_data[2] = 'c'; // SerialTransmit(s, 0x00, 3); //} SerialData * s = SerialDataAvailable(); if (s != 0) { switch (s->receive_data[0]) { case 0x88: // Reset everything (all axis back to limit switches) { task = TASK_LIMIT_SWITCH_Y; x_axis.state = 1; y_axis.state = 1; z_axis.state = 1; s->transmit_data[0] = 0x88; SerialTransmit (s, 0x00, 1); // Transmit to master device break; } case 0x77: // Ping (and location/status information) { s->transmit_data[0] = 0x77; // TODO: find a better way to do this step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; // Disable the step timer int32_t x = AxisGetCurrentPosition(&x_axis); int32_t y = AxisGetCurrentPosition(&y_axis); int32_t z = AxisGetCurrentPosition(&z_axis); step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // Enable the step timer s->transmit_data[1] = x & 0xFF; x = x >> 8; s->transmit_data[2] = x & 0xFF; x = x >> 8; s->transmit_data[3] = x & 0xFF; x = x >> 8; s->transmit_data[4] = x & 0xFF; s->transmit_data[5] = y & 0xFF; y = y >> 8; s->transmit_data[6] = y & 0xFF; y = y >> 8; s->transmit_data[7] = y & 0xFF; y = y >> 8; s->transmit_data[8] = y & 0xFF; s->transmit_data[9] = z & 0xFF; z = z >> 8; s->transmit_data[10] = z & 0xFF; z = z >> 8; s->transmit_data[11] = z & 0xFF; z = z >> 8; s->transmit_data[12] = z & 0xFF; uint8_t status_bits = 0; if (IsMoving (&x_axis)) { status_bits |= 0x01; } if (IsMoving (&y_axis)) { status_bits |= 0x02; } if (IsMoving (&z_axis)) { status_bits |= 0x04; } s->transmit_data[13] = status_bits; //step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; // Disable the step timer buffer_lock = 1; s->transmit_data[14] = RingBufferCount(&location_buffer); buffer_lock = 0; //step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // Enable the step timer //s->transmit_data[14] = location_buffer_size; SerialTransmit (s, 0x00, 15); // Transmit to master device break; } case 0x32: // Set Position + Speed { Location_t l; /* Bytes 1:2 are time in milliseconds */ l.time = decode_uint16_t(&(s->receive_data[1])); /* Bytes 3:14 are position */ l.x = decode_uint32_t(&(s->receive_data[3])); l.y = decode_uint32_t(&(s->receive_data[7])); l.z = decode_uint32_t(&(s->receive_data[11])); // Add the new location to the buffer //step_timer->INTCTRLA &= ~TC1_OVFINTLVL_gm; // Disable the step timer buffer_lock = 1; if (!RingBufferIsFull(&location_buffer)) { RingBufferAdd(&location_buffer, l); } //if (location_buffer_size < 1) //{ // nextLocation = l; // location_buffer_size++; //} s->transmit_data[1] = RingBufferCount(&location_buffer); buffer_lock = 0; //step_timer->INTCTRLA |= TC_OVFINTLVL_LO_gc; // Enable the step timer s->transmit_data[0] = 0x32; //s->transmit_data[1] = location_buffer_size; SerialTransmit(s, 0x00, 2); break; } } } else if (task == TASK_LIMIT_SWITCH_Y) { uint8_t v = LimitSwitchHelper(&x_axis); v &= LimitSwitchHelper(&y_axis); v &= LimitSwitchHelper(&z_axis); if (v) { task = 0; } } }