//__attribute__ ((section (".irq"))) //__attribute__ ((interrupt("IRQ"))) void isr(void) { uint32_t pending; nirqpass = 0; while ((pending = *NIPEND)) { if(bit_is_set(pending, INT_NUM_TMR)) { /* dispatch to individual timer isrs if they exist */ /* timer isrs are responsible for determining if they * caused an interrupt */ /* and clearing their own interrupt flags */ if (tmr_isr_funcs[0] != 0) { (tmr_isr_funcs[0])(); } if (tmr_isr_funcs[1] != 0) { (tmr_isr_funcs[1])(); } if (tmr_isr_funcs[2] != 0) { (tmr_isr_funcs[2])(); } if (tmr_isr_funcs[3] != 0) { (tmr_isr_funcs[3])(); } } if(bit_is_set(pending, INT_NUM_MACA)) { if(maca_isr != 0) { maca_isr(); } } if(bit_is_set(pending, INT_NUM_UART1)) { if (ttyInterrupt != 0) { ttyInterrupt(); } } if(bit_is_set(pending, INT_NUM_UART2)) { if(uart2_isr != 0) { uart2_isr(); } } if(bit_is_set(pending, INT_NUM_CRM)) { if(rtc_wu_evt() && (rtc_isr != 0)) { rtc_isr(); } if(kbi_evnt(4) && (kbi4_isr != 0)) { kbi4_isr(); } if(kbi_evnt(5) && (kbi5_isr != 0)) { kbi5_isr(); } if(kbi_evnt(6) && (kbi6_isr != 0)) { kbi6_isr(); } if(kbi_evnt(7) && (kbi7_isr != 0)) { kbi7_isr(); } if (CRM->STATUSbits.CAL_DONE && CRM->CAL_CNTLbits.CAL_IEN && cal_isr) { CRM->STATUSbits.CAL_DONE = 0; cal_isr(); } } if(bit_is_set(pending, INT_NUM_ASM)) { if(asm_isr != 0) { asm_isr(); } } if (bit_is_set(pending, INT_NUM_I2C)) { if (i2c_isr != 0) { i2c_isr(); } } *INTFRC = 0; /* stop forcing interrupts */ nirqpass++; } }
void HALT_Until_Event(HALT_EVENT halt_event) { BOOLEAN cont; cont = true; while(cont) { lp_setHaltMode(); // process during waiting i2c_isr(0); i2c_isr(1); switch(halt_event) { case HALT_I2C1_END: if(i2c_get_status(1) <= I2C_MODE_ERROR) cont = false; break; case HALT_I2C0_END: if(i2c_get_status(0) <= I2C_MODE_ERROR) cont = false; break; default: cont = false; break; } wdt_clear(); } return; }
void i2c_update(void) { // TODO: Multiple ports if (I2C_2.state == IDLE) { // If there is data to send if (I2C_2.frameToSend == True) { I2C_2.state = START; i2c_isr(I2C2); } } }
void __attribute__((interrupt, auto_psv)) _MI2C1Interrupt(void) { IFS1bits.MI2C1IF = 0; //Clear flag i2c_isr(); }
void i2c_isr(uint8_t p) { I2CModule_t * mod; // Get a reference to the module structure switch (p) { case I2C2: mod = &I2C_2; break; default: return; } switch (mod->state) { case IDLE: break; case START: I2CStart(mod->moduleName); mod->state = ADDRESS; I2C_2.dataDirection = WRITING; break; case ADDRESS: switch (mod->dataDirection) { case READING: I2CSendByte(mod->moduleName, mod->frame->address + 1); mod->state = CHECK_ACK; break; case WRITING: I2CSendByte(mod->moduleName, mod->frame->address); mod->state = CHECK_ACK; break; } break; case CHECK_ACK: if (I2CByteWasAcknowledged(mod->moduleName) == True) { switch (mod->dataDirection) { case READING: mod->state = READ; break; case WRITING: mod->state = WRITE; break; } } else { mod->frame->success = False; mod->state = STOP; } i2c_isr(mod->moduleName); break; case RESTART: I2CRepeatStart(mod->moduleName); mod->dataDirection = READING; mod->state = ADDRESS; break; case READ_START: I2CReceiverEnable(mod->moduleName, TRUE); mod->state = READ; break; case READ: mod->frame->rx_buf[mod->frame->rx_buf_index++] = I2CGetByte(mod->moduleName); // If we need to read more bytes send an ACK if (mod->frame->rx_buf_index <= mod->frame->bytesToRead) { I2CAcknowledgeByte(mod->moduleName, True); // Send an ACK mod->state = READ_START; // Prepare for the next byte } else { I2CAcknowledgeByte(mod->moduleName, False); // Send a NACK mod->frame->success = True; mod->state = STOP; // Prepare for a stop condition } break; case WRITE: // If there are still bytes to send if (mod->frame->tx_buf_index < mod->frame->tx_buf_size) { I2CSendByte(mod->moduleName, mod->frame->tx_buf[mod->frame->tx_buf_index++]); } else { // If we need to read some bytes if (mod->frame->bytesToRead > 0) { mod->state = RESTART; // Send a restart condition } else { mod->frame->success = True; mod->state = STOP; // Send a stop condition } i2c_isr(mod->moduleName); // Re-run this function to call stop/restart // TODO: Perhaps there is a better way to do this..! } break; case STOP: I2CStop(mod->moduleName); mod->frameToSend = False; mod->state = IDLE; // Tell the owner of the frame that it has complete or failed if (mod->frame->success == True) { mod->frame->callback(); } else { mod->frame->error(); } break; case BUSERROR: led12 = 1; // TODO: Something..! while(1); // Don't know what to do here yet..! break; } }
void TWI1_Handler() { i2c_isr( 1 ); }
void TWI0_Handler() { i2c_isr( 0 ); }
void i2c1_isr() { i2c_isr( 1 ); }
void i2c0_isr() { i2c_isr( 0 ); }
int32_t i2c_send_sequence( uint8_t ch, uint16_t *sequence, uint32_t sequence_length, uint8_t *received_data, void ( *callback_fn )( void* ), void *user_data ) { int32_t result = 0; volatile I2C_Channel *channel = &( i2c_channels[ch - ISSI_I2C_FirstBus_define] ); uint8_t address; #if defined(_kinetis_) uint8_t status; volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; volatile uint8_t *I2C_S = (uint8_t*)(&I2C0_S) + i2c_offset[ch]; volatile uint8_t *I2C_D = (uint8_t*)(&I2C0_D) + i2c_offset[ch]; #elif defined(_sam_) Twi *twi_dev = twi_devs[ch]; #endif if ( channel->status == I2C_BUSY ) { return -1; } // Check if there are back-to-back errors // in succession if ( channel->last_error > 5 ) { warn_msg("I2C Bus Error: "); printInt8( ch ); print(" errors: "); printInt32( channel->error_count ); print( NL ); } // Debug /* for ( uint8_t c = 0; c < sequence_length; c++ ) { printHex( sequence[c] ); print(" "); } print(NL); */ channel->sequence = sequence; channel->sequence_end = sequence + sequence_length; channel->received_data = received_data; channel->status = I2C_BUSY; channel->txrx = I2C_WRITING; channel->callback_fn = callback_fn; channel->user_data = user_data; // reads_ahead does not need to be initialized #if defined(_kinetis_) // Acknowledge the interrupt request, just in case *I2C_S |= I2C_S_IICIF; *I2C_C1 = ( I2C_C1_IICEN | I2C_C1_IICIE ); // Generate a start condition and prepare for transmitting. *I2C_C1 |= ( I2C_C1_MST | I2C_C1_TX ); status = *I2C_S; if ( status & I2C_S_ARBL ) { warn_print("Arbitration lost"); result = -1; goto i2c_send_sequence_cleanup; } // Write the first (address) byte. address = *channel->sequence++; *I2C_D = address; // Everything is OK. return result; i2c_send_sequence_cleanup: // Record error, and reset last error counter channel->error_count++; channel->last_error++; // Generate STOP and disable further interrupts. *I2C_C1 &= ~( I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX ); channel->status = I2C_ERROR; #elif defined(_sam_) // Convert 8 bit address to 7bit + RW address = *channel->sequence++; //print("Address: "); //printHex( address ); //print( NL ); uint8_t mread = address & 1; address >>= 1; // Set slave address twi_dev->TWI_MMR = TWI_MMR_DADR(address) | (mread ? TWI_MMR_MREAD : 0); // Enable interrupts twi_dev->TWI_IER = TWI_IER_RXRDY | TWI_IER_TXRDY | TWI_IER_TXCOMP | TWI_IER_ARBLST; //twi_dev->TWI_IDR = 0xFFFFFFFF; // Generate a start condition twi_dev->TWI_CR |= TWI_CR_START; // Fire off the first read or write. // The first (address) byte is automatically trasmitted before any data // Arbitration errors will be handled in the isr i2c_isr(ch); // Everything is OK. return result; #endif return result; }