Пример #1
0
Файл: uart.c Проект: nesl/sos-2x
static inline void uart_send_byte(uint8_t byte) {
	static uint8_t saved_state;

	if ((state[TX].flags & UART_CRC_FLAG) && (state[TX].hdlc_state == HDLC_DATA)) {
		state[TX].crc = crcByte(state[TX].crc, byte);
	}
	if (state[TX].hdlc_state == HDLC_ESCAPE) {
		uart_setByte(0x20 ^ byte);
		state[TX].hdlc_state = saved_state;
	} else if ((byte == HDLC_FLAG) || (byte == HDLC_CTR_ESC) || (byte == HDLC_EXT)) {
		saved_state = state[TX].hdlc_state;
		state[TX].hdlc_state = HDLC_ESCAPE;
		uart_setByte(HDLC_CTR_ESC);
		return;
	} else {
		uart_setByte(byte);
	}
	state[TX].idx++;
}
Пример #2
0
Файл: uart.c Проект: nesl/sos-2x
/**
 * @brief ISR for reception
 * This is the writer of rx_queue.
 */
uart_recv_interrupt() {
#ifdef SOS_USE_PREEMPTION
	HAS_PREEMPTION_SECTION;
	DISABLE_PREEMPTION();
#endif
	
	uint8_t err;
	uint8_t byte_in;
	static uint16_t crc_in;
	static uint8_t saved_state;
	SOS_MEASUREMENT_IDLE_END()
	LED_DBG(LED_YELLOW_TOGGLE);
	//! NOTE that the order has to be this in AVR
	err = uart_checkError();
	byte_in = uart_getByte();

	//DEBUG("uart_recv_interrupt... %d %d %d %d %d\n", byte_in, err, 
	//		state[RX].state, state[RX].msg_state, state[RX].hdlc_state);
	switch (state[RX].state) {
		case UART_IDLE:
			if ((err != 0) || (byte_in != HDLC_FLAG)) {
				break;
			}
			state[RX].state = UART_HDLC_START;
			break;

		case UART_HDLC_START:
		case UART_PROTOCOL:
			if (err != 0) {
				uart_reset_recv();
				break;
			}

			switch (byte_in) {
				//! ignore repeated start symbols
				case HDLC_FLAG:
					state[RX].state = UART_HDLC_START;
					break;

				case HDLC_SOS_MSG:
					if(state[RX].msgHdr == NULL) {
						state[RX].msgHdr = msg_create();
					} else {
						if((state[RX].msgHdr->data != NULL) &&
								(flag_msg_release(state[RX].msgHdr->flag))){
							ker_free(state[RX].msgHdr->data);
							state[RX].msgHdr->flag &= ~SOS_MSG_RELEASE;
						}
					}
					if(state[RX].msgHdr != NULL) {
						state[RX].msg_state = SOS_MSG_RX_HDR;
						state[RX].crc = crcByte(0, byte_in);
						state[RX].flags |= UART_SOS_MSG_FLAG;
						state[RX].idx = 0;
						state[RX].state = UART_DATA;
						state[RX].hdlc_state = HDLC_DATA;
					} else {
						// need to generate no mem error
						uart_reset_recv();
					}
					break;

				case HDLC_RAW:
					if ((state[RX].buff = ker_malloc(UART_MAX_MSG_LEN, UART_PID)) != NULL) {
						state[RX].msg_state = SOS_MSG_RX_RAW;
						if (state[RX].flags & UART_CRC_FLAG) {
							state[RX].crc = crcByte(0, byte_in);
						}
						state[RX].state = UART_DATA;
						state[RX].hdlc_state = HDLC_DATA;
					} else {
						uart_reset_recv();
					}
					state[RX].idx = 0;
					break;

				default:
					uart_reset_recv();
					break;
				}
				break;

		case UART_DATA:
				if (err != 0) {
					uart_reset_recv();
					break;
				}

				// recieve an escape byte, wait for next byte
				if (byte_in  == HDLC_CTR_ESC) {
					saved_state = state[RX].hdlc_state;
					state[RX].hdlc_state = HDLC_ESCAPE;
					break;
				}

				if (byte_in == HDLC_FLAG) { // got an end of message symbol
					/*
					if (state[RX].msg_state == SOS_MSG_RX_RAW) {
						// end of raw recieve
						// should bundle and send off
						// trash for now
							 state[RX].hdlc_state = HDLC_IDLE;
							 state[RX].state = UART_IDLE;
							 state[RX].flags |= UART_DATA_RDY_FLAG;
							 uart_read_done(state[RX].idx, 0);
					} else {
						// got an end of message symbol early
						*/
						uart_reset_recv();
					//}
					break;
				}

				if (state[RX].hdlc_state == HDLC_ESCAPE) {
					byte_in ^= 0x20;
					state[RX].hdlc_state = saved_state;
				}

				switch (state[RX].msg_state) {
					case SOS_MSG_RX_HDR:
						if (byte_in == HDLC_FLAG) {  // got an end of message symbol
							uart_reset_recv();
							break;
						}
						uint8_t *tmpPtr = (uint8_t*)(state[RX].msgHdr);
						tmpPtr[state[RX].idx++] = byte_in;

						state[RX].crc = crcByte(state[RX].crc, byte_in);

						if (state[RX].idx == SOS_MSG_HEADER_SIZE) {
							// if (state[RX].msgLen != state[RX].msgHdr->len) ????????
							state[RX].msgLen = state[RX].msgHdr->len;

							if (state[RX].msgLen < UART_MAX_MSG_LEN) {
								if (state[RX].msgLen != 0) {
									state[RX].buff = (uint8_t*)ker_malloc(state[RX].msgLen, UART_PID);
									if (state[RX].buff != NULL) {
										state[RX].msgHdr->data = state[RX].buff;
										state[RX].msgHdr->flag = SOS_MSG_RELEASE;
										state[RX].msg_state = SOS_MSG_RX_DATA;
										state[RX].idx = 0;
									} else {
										uart_reset_recv();
									}
								} else { // 0 length packet go straight to crc
									state[RX].msgHdr->flag &= ~SOS_MSG_RELEASE;
									state[RX].msgHdr->data = NULL;
									state[RX].msg_state = SOS_MSG_RX_CRC_LOW;
								}
							} else { // invalid msg length
								uart_reset_recv();
							}
						}
						break;

					case SOS_MSG_RX_RAW:
					case SOS_MSG_RX_DATA:
						if (err != 0) {
							uart_reset_recv();
							return;
						}
						state[RX].buff[state[RX].idx++] = byte_in;
						if (state[RX].flags & UART_CRC_FLAG) {
							state[RX].crc = crcByte(state[RX].crc, byte_in);
						}
						if (state[RX].idx == state[RX].msgLen) {
							if (state[RX].flags & UART_SOS_MSG_FLAG) {
								state[RX].hdlc_state = HDLC_CRC;
								state[RX].msg_state = SOS_MSG_RX_CRC_LOW;
							} else {
								// rx buffer overflow
								uart_reset_recv();
							}
						}
						break;

					case SOS_MSG_RX_CRC_LOW:
						crc_in = byte_in;
						state[RX].msg_state = SOS_MSG_RX_CRC_HIGH;
						break;

					case SOS_MSG_RX_CRC_HIGH:
						crc_in |= ((uint16_t)(byte_in) << 8);
						state[RX].hdlc_state = HDLC_PADDING;
						state[RX].msg_state = SOS_MSG_RX_END;
						state[RX].state = UART_HDLC_STOP;
						break;

					case SOS_MSG_RX_END:  // should never get here
					default:
						uart_reset_recv();
						break;
				}
				break;

		case UART_HDLC_STOP:
				if (byte_in != HDLC_FLAG) {
					// silently drop until hdlc stop symbol
					break;
				} else { // sos msg rx done
					state[RX].hdlc_state = HDLC_IDLE;
					if(crc_in == state[RX].crc) {
#ifndef NO_SOS_UART_MGR
						set_uart_address(entohs(state[RX].msgHdr->saddr));
#endif
            if(state[RX].msgHdr->type == MSG_TIMESTAMP){
              uint32_t timestp = ker_systime32();
              memcpy(((uint8_t*)(state[RX].msgHdr->data) + sizeof(uint32_t)),(uint8_t*)(&timestp),sizeof(uint32_t));

            }
						handle_incoming_msg(state[RX].msgHdr, SOS_MSG_UART_IO);
						state[RX].msgHdr = NULL;
					} else {
						msg_dispose(state[RX].msgHdr);
						state[RX].msgHdr = NULL;
					}
					state[RX].state = UART_IDLE;
					state[RX].msg_state = SOS_MSG_NO_STATE;
					state[RX].hdlc_state = HDLC_IDLE;
					//uart_reset_recv();

					//state[RX].msg_state = SOS_MSG_NO_STATE;
					//state[RX].state = UART_HDLC_START;
				}
				break;
				// XXX fall through

		default:
				uart_reset_recv();
				break;
	} // state[RX].state

#ifdef SOS_USE_PREEMPTION
  // enable interrupts because 
  // enabling preemption can cause one to occur
  ENABLE_GLOBAL_INTERRUPTS();
  // enable preemption
  ENABLE_PREEMPTION(NULL);
#endif
}
Пример #3
0
Файл: uart.c Проект: nesl/sos-2x
uart_send_interrupt() {
#ifdef SOS_USE_PREEMPTION
	HAS_PREEMPTION_SECTION;
	DISABLE_PREEMPTION();
#endif
	SOS_MEASUREMENT_IDLE_END();
	LED_DBG(LED_GREEN_TOGGLE);

	//DEBUG("uart_send_interrupt %d %d %d\n", state[TX].state, state[TX].msg_state,
	//		state[TX].hdlc_state);
	switch (state[TX].state) {
		case UART_HDLC_START:
			uart_setByte((state[TX].flags & UART_SOS_MSG_FLAG)?HDLC_SOS_MSG:HDLC_RAW);
			state[TX].hdlc_state = HDLC_DATA;
			state[TX].state = UART_PROTOCOL;
			if (state[TX].flags & UART_CRC_FLAG) {
				state[TX].crc = crcByte(0, (state[TX].flags & UART_SOS_MSG_FLAG)?HDLC_SOS_MSG:HDLC_RAW);
			}
			break;

		case UART_PROTOCOL:
			state[TX].state = UART_DATA;
			if (state[TX].flags & UART_SOS_MSG_FLAG) {
				state[TX].msg_state = SOS_MSG_TX_HDR;
			} else {
				state[TX].msg_state = SOS_MSG_TX_RAW;
			}
			// set state and fall through
		case UART_DATA:
			switch (state[TX].msg_state) {
				case SOS_MSG_TX_HDR:
					uart_send_byte(((uint8_t*)(state[TX].msgHdr))[state[TX].idx]);
					if ((state[TX].idx == SOS_MSG_HEADER_SIZE) && (state[TX].hdlc_state != HDLC_ESCAPE)) {
						state[TX].idx = 0;
						if (state[TX].msgHdr->len != 0) {
							state[TX].msg_state = SOS_MSG_TX_DATA;
						} else {
							state[TX].hdlc_state = HDLC_CRC;
							state[TX].msg_state = SOS_MSG_TX_CRC_LOW;
						}
					}
					break;

				case SOS_MSG_TX_DATA:
				case SOS_MSG_TX_RAW:
					uart_send_byte(state[TX].buff[state[TX].idx]);
					if ((state[TX].idx == state[TX].msgLen) && (state[TX].hdlc_state != HDLC_ESCAPE)) {
						if (state[TX].flags & UART_CRC_FLAG) {
							state[TX].hdlc_state = HDLC_CRC;
							state[TX].msg_state = SOS_MSG_TX_CRC_LOW;
						} else { // no crc
							state[TX].state = UART_END;
							uart_setByte(HDLC_FLAG);
						}
					}
					break;

				case SOS_MSG_TX_CRC_LOW:
					uart_send_byte((uint8_t)(state[TX].crc));
					if (state[TX].hdlc_state != HDLC_ESCAPE) { //! crc was escaped, resend
						state[TX].msg_state = SOS_MSG_TX_CRC_HIGH;
					}
					break;

				case SOS_MSG_TX_CRC_HIGH:
					uart_send_byte((uint8_t)(state[TX].crc >> 8));
					if (state[TX].hdlc_state != HDLC_ESCAPE) { //! resend low byte
						state[TX].msg_state = SOS_MSG_TX_END;
						state[TX].state = UART_HDLC_STOP;
					}
					break;
				default:
					break;
			}
			break;

		case UART_HDLC_STOP:
			uart_setByte(HDLC_FLAG);
			state[TX].state = UART_END;
			state[TX].msg_state = SOS_MSG_NO_STATE;
			break;

		case UART_END:
			//DEBUG("disable Tx in uart.c\n");
			uart_disable_tx();
			state[TX].state = UART_IDLE;
			state[TX].hdlc_state = HDLC_IDLE;
			uart_send_done(state[TX].flags & ~UART_ERROR_FLAG);
			//DEBUG("uart_disable_tx\n");
			break;

		default:
			//DEBUG("In Default...\n");
			//DEBUG("disable Tx in uart.c\n");
			uart_disable_tx();
			state[TX].flags |= UART_ERROR_FLAG;
			state[TX].state = UART_IDLE;
			state[TX].hdlc_state = HDLC_IDLE;
			uart_send_done(state[TX].flags & ~UART_ERROR_FLAG);
			break;
	}
	//DEBUG("end uart_send_interrupt %d %d %d\n", state[TX].state, state[TX].msg_state,
	//		state[TX].hdlc_state);

#ifdef SOS_USE_PREEMPTION
  // enable interrupts because 
  // enabling preemption can cause one to occur
  ENABLE_GLOBAL_INTERRUPTS();
  // enable preemption
  ENABLE_PREEMPTION(NULL);
#endif
}
Пример #4
0
i2c_interrupt() {

	static uint8_t addrFailCnt;

    SOS_MEASUREMENT_IDLE_END();

		// TWSR & TW_STATUS_MASK
		switch (TWSR) {
			/*************************
			 * Master General States *
			 *************************/
			case TWI_START: /* 0x08 */
				addrFailCnt = 0;
				i2c.idx = 0;
        // Fall through!

			case TWI_REP_START: /* 0x10 */
				i2c_setByte(i2c.addr|((i2c.flags & I2C_TX_FLAG)?0:1));  // only set R/W bit if reading
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE));
				break;

			case TWI_ARB_LOST: /* 0x38 */
				i2c_setCtrlReg((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE)); // Initate a (RE)START condition
				// TWI hardware will resend start when bus is free and signal TWI_RESTART
				break;


		
				/*****************************
				 * Master Transmitter States *
				 *****************************/
			case TWI_MTX_ADR_ACK: /* 0x18 */
				i2c.state = I2C_MASTER_TX;
				if (i2c.flags & I2C_SOS_MSG_FLAG) {
					// this is a difference between the i2c and uart
					// uart uses a protocol byte for BOTH raw and sos_msgs
					// i2c ONLY sends a protocol byte in the case of a sos_msg
					i2c_setByte(HDLC_SOS_MSG);
					i2c.msg_state = SOS_MSG_TX_HDR;
					// this is a sos_msg so a crc is required
					i2c.crc = crcByte(0, HDLC_SOS_MSG);
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE));
					break;
				} else {
					i2c.msg_state = SOS_MSG_TX_RAW;
				} // fall through

			case TWI_MTX_DATA_ACK: /* 0x28 */
				switch (i2c.msg_state) {
					case SOS_MSG_TX_HDR:
						i2c_setByte(((uint8_t*)(i2c.msgBuf))[i2c.idx]);
						// this is a sos_msg so a crc is required
						i2c.crc = crcByte(i2c.crc, ((uint8_t*)(i2c.msgBuf))[i2c.idx]);
						i2c.idx++;
						if (i2c.idx == SOS_MSG_HEADER_SIZE) {
							i2c.idx = 0;
							i2c.txPending = i2c.msgLen + SOS_MSG_CRC_SIZE;
							i2c.msg_state = SOS_MSG_TX_DATA;
						}
						break;

					case SOS_MSG_TX_RAW:
					case SOS_MSG_TX_DATA:
						i2c_setByte(i2c.dataBuf[i2c.idx]);
						if (i2c.flags & I2C_CRC_FLAG) {
							i2c.crc = crcByte(i2c.crc, i2c.dataBuf[i2c.idx]);
						}
						i2c.idx++;
						if (i2c.idx == i2c.msgLen) {
							if (!(i2c.flags & I2C_CRC_FLAG)) {
								// send stop bit and reset interface to ready state
								i2c.txPending = 0;
								i2c.msg_state = SOS_MSG_TX_END;
							} else {
								i2c.txPending = SOS_MSG_CRC_SIZE;  // no unsent bytes
								i2c.msg_state = SOS_MSG_TX_CRC_LOW;
							}
						}
						break;

					case SOS_MSG_TX_CRC_LOW:
						i2c_setByte((uint8_t)(i2c.crc));
						i2c.txPending--;
						i2c.msg_state = SOS_MSG_TX_CRC_HIGH;
						break;

					case SOS_MSG_TX_CRC_HIGH:
						i2c_setByte((uint8_t)(i2c.crc>>8));
						i2c.txPending--;
						i2c.msg_state = SOS_MSG_TX_END;
						break;

					case SOS_MSG_TX_END:
						// send stop bit and reset interface to ready state
						i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE));
						i2c_send_done(i2c.flags);
						i2c.state = restoreState();
						return;
					default:
						break;
				}
				// normal send byte all stop conditions must return and not get here
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE));
				break;

			case TWI_MTX_ADR_NACK: /* 0x20 */
				if (addrFailCnt++ < MAX_ADDR_FAIL) {
					// try restarting MAX_ADDR_FAIL times then fail
					i2c_setCtrlReg((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE));
				} else {
					// reset i2c and send msg fail to process
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE));
					i2c_send_done(i2c.flags|I2C_ERROR_FLAG);
					i2c.state = restoreState();
				}
				break;

			case TWI_MTX_DATA_NACK: /* 0x30 */
				// reset i2c and send msg fail to process
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE));
				i2c.txPending = i2c.txPending - i2c.idx + 1; // last byte failed
				i2c_send_done(i2c.flags|I2C_BUFF_ERR_FLAG);
				i2c.state = restoreState();
				break;


			
				/***************************
				 * Master Receiver  States *
				 ***************************/
			case TWI_MRX_ADR_ACK: /* 0x40 */
				i2c.state = I2C_MASTER_RX;
				i2c.rxStatus = i2c.flags;
				// all master rx are done in raw mode with NO protocol byte
				i2c.msg_state = SOS_MSG_RX_RAW;
				// a sos message will never be recieved as a manster
				if (i2c.msgLen == 1) {
					i2c.msg_state = SOS_MSG_RX_END;
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE));
				} else {
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				}
				break;

			case TWI_MRX_DATA_ACK: /* 0x50 */
				i2c.dataBuf[i2c.idx++] = i2c_getByte();

				if (i2c.idx < (i2c.msgLen-1)) {
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				} else { // unset TWEA (Send NACK after next/last byte)
					i2c.msg_state = SOS_MSG_RX_END;
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE));
				}
				break;

			case TWI_MRX_ADR_NACK: /* 0x48 */
				if (addrFailCnt++ < MAX_ADDR_FAIL) {
					// tryrestarting MAX_ADDR_FAIL times then fail
					i2c_setCtrlReg((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE));
					break;
				}
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE));

				// return data
				i2c_read_done(i2c.dataBuf, i2c.idx, i2c.rxStatus);
				i2c.idx = 0;
				i2c.rxStatus = 0;

				i2c.state = restoreState();
				break;

			case TWI_MRX_DATA_NACK: /* 0x58 */
				i2c.dataBuf[i2c.idx++] = i2c_getByte();

				if (i2c.idx < i2c.msgLen) {
					// nack from master indication rx done
					// send stop bit, clear interrupt and reset interface to ready state
					i2c.rxStatus |= I2C_BUFF_ERR_FLAG;
				}

				// set flags and return data
				i2c.rxStatus |= I2C_BUFF_DIRTY_FLAG;
				
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE));
				
				i2c_read_done(i2c.dataBuf, i2c.idx, i2c.rxStatus);
				i2c.idx = 0;
				i2c.rxStatus = 0;
				
				i2c.state = restoreState();
				break;


			
				/****************************
				 * Slave Transmitter States *
				 ****************************/
			case TWI_STX_ADR_ACK: /* 0xA8 */
			case TWI_STX_ADR_ACK_M_ARB_LOST: /* 0xB0 */
				if (i2c.state != I2C_SLAVE_WAIT) {
					i2c_send_done(i2c.flags|I2C_ERROR_FLAG);
					break;
				} else {
					saveState(i2c.state);
					i2c.state = I2C_SLAVE_TX;
					i2c.msg_state = SOS_MSG_TX_RAW;
				}
				// fall through

			case TWI_STX_DATA_ACK: /* 0xB8 */
				if (i2c.msg_state == SOS_MSG_TX_RAW) {
					i2c_setByte(i2c.dataBuf[i2c.idx++]);

					// unset TWEA (Send NACK after next/last byte)
					if (i2c.msgLen == i2c.idx) {
						i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE));
						i2c.txPending = 1; // last byte failed
						i2c.msg_state = SOS_MSG_TX_END;
					} else { // Reset the TWI Interupt to wait to ack next byte
						i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
					}
				}
				break;

			case TWI_STX_DATA_NACK: /* 0xC0 */
				// Master has sent a NACK before expected amount of data was sent.
				// set dirty bit on send buffer go to end state and issue send done
				if (i2c.msg_state != SOS_MSG_TX_END) { 
					i2c.txPending = i2c.txPending - i2c.idx + 1; // last byte failed
					i2c.msg_state = SOS_MSG_TX_END;
				} else {
					i2c.txPending = 0;
				}

				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));

				if (i2c.msg_state == SOS_MSG_TX_END) {
					i2c.msg_state = SOS_MSG_NO_STATE;
					i2c_send_done(i2c.flags);
				}
				break;

			case TWI_STX_DATA_ACK_LAST_BYTE: /* 0xC8 */
				i2c.msg_state = SOS_MSG_NO_STATE;
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				i2c_send_done(i2c.flags|I2C_BUFF_ERR_FLAG);
				break;



				/*************************
				 * Slave Receiver States *
				 *************************/
				// all receptions are done in a raw mode
				// if it is a sos message it it will be packed later
			case TWI_SRX_GEN_ACK: /* 0x70 */
			case TWI_SRX_GEN_ACK_M_ARB_LOST: /* 0x78 */
				i2c.rxStatus = I2C_GEN_ADDR_FLAG;
				// fall through

			case TWI_SRX_ADR_ACK: /* 0x60 */
			case TWI_SRX_ADR_ACK_M_ARB_LOST: /* 0x68 */
				saveState(i2c.state);
				i2c.state = I2C_SLAVE_RX;
				i2c.msg_state = SOS_MSG_RX_RAW;
				i2c.idx = 0;
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				break;

			case TWI_SRX_ADR_DATA_ACK: /* 0x80 */
			case TWI_SRX_GEN_DATA_ACK: /* 0x90 */
				if (i2c.msg_state == SOS_MSG_RX_RAW) {
					i2c.rxDataBuf[i2c.idx++] = i2c_getByte();
					if (i2c.idx >= I2C_MAX_MSG_LEN) { // buffer overflow
						i2c.msg_state = SOS_MSG_RX_END;
						
						// set flags and return data
						i2c.rxStatus |= (I2C_BUFF_DIRTY_FLAG|I2C_BUFF_ERR_FLAG);
						i2c_read_done(i2c.rxDataBuf, i2c.idx, i2c.rxStatus);
						i2c.idx = 0;
						i2c.rxStatus = 0;
					}
				}
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				break;

			case TWI_SRX_ADR_DATA_NACK: /* 0x88 */
			case TWI_SRX_GEN_DATA_NACK: /* 0x98 */
				// switch to not addressed mode
				if (i2c.msg_state == SOS_MSG_RX_RAW) {
					
					// set flags and return data
					i2c.rxStatus |= I2C_BUFF_DIRTY_FLAG;
					i2c_read_done(i2c.rxDataBuf, i2c.idx, i2c.rxStatus);
					i2c.idx = 0;
					i2c.rxStatus = 0;
					i2c.msg_state = SOS_MSG_RX_END;
				}
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				break;

			case TWI_SRX_STOP_RESTART: /* 0xA0 */
				// reset reciever
				i2c.msg_state = SOS_MSG_NO_STATE;
				if (i2c.idx > 0) {
					// need to make sure data has been read
					i2c.rxStatus |= I2C_BUFF_DIRTY_FLAG;
					i2c_read_done(i2c.rxDataBuf, i2c.idx, i2c.rxStatus);
					i2c.idx = 0;
					i2c.rxStatus = 0;
				}
				i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
				i2c.state = restoreState();
				break;

				
			
				/***************
				 * Misc States *
				 ***************/
				//case TWI_NO_STATE: /* 0xF8 */
			case TWI_BUS_ERROR: /* 0x00 */
			default:
				{
					uint8_t twiStatus=0;
					// Store TWSR and automatically sets clears noErrors bit.
					twiStatus = TWSR;
					// Clear TWINT and reset TWI Interface
					i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
					i2c.state = I2C_IDLE;
					// should really be i2c_error
					i2c_send_done(I2C_NULL_FLAG);
					break;
				}
		}
}
Пример #5
0
/**
 * Send MSG_I2C_READ_DONE
 */
void i2c_read_done(uint8_t *buff, uint8_t len, uint8_t status) {

	uint8_t *bufPtr = NULL;
	Message *msgPtr = NULL;

	// this is a problem that should be handled
	if (buff == NULL) {
		return;
	}

	if ((i2c_sys.calling_mod_id != NULL_PID) && (status & I2C_SYS_ERROR_FLAG)) {
		goto post_error_msg;
	}

	// the bus was reserved the read was of the length we requested
	if ((i2c_sys.calling_mod_id != NULL_PID) && (len == i2c_sys.rxLen) && 
			// the data was recieved in the correct mode
			(((i2c_sys.state == I2C_SYS_MASTER_RX) && (I2C_SYS_MASTER_FLAG & status)) ||
			 ((i2c_sys.state == I2C_SYS_SLAVE_RX) && !(I2C_SYS_MASTER_FLAG & status)))) {

		// reserved read done will only be raw reads, wrap in message and send
		post_long(
				i2c_sys.calling_mod_id,
				I2C_PID,
				MSG_I2C_READ_DONE,
				len,
				buff,
				SOS_MSG_RELEASE|SOS_MSG_HIGH_PRIORITY);
		i2c_sys.state = (i2c_sys.flags & I2C_SYS_MASTER_FLAG)?I2C_SYS_MASTER_WAIT:I2C_SYS_SLAVE_WAIT;
		return;
	}

	// there appers to be a bug in avr-gcc this a work around to make sure
	// the cast to message works correctly
	// the following code seems to cat the value 0x800008 independent of what
	// buff actually ii2c_sys.  this has no correlation to the data in buff or the 
	// value of the pointer the cast (along with many others that should) works
	// in gdb but fail to execute correctly when compilied
	/* bufPtr = &buff[HDLC_PROTOCOL_SIZE]; */

	// DO NOT CHANGE THIS SECTION OF CODE
	// start of section
	bufPtr = buff+1;
	// end of DO NOT CHANGE SECTION
		
	// if it passes sanity checks give it to the scheduler
	if (!(I2C_SYS_MASTER_FLAG & status) && (len >= SOS_MSG_HEADER_SIZE) && (buff[0] == HDLC_SOS_MSG)) {

		if ((len >= (HDLC_PROTOCOL_SIZE + SOS_MSG_HEADER_SIZE + ((Message*)bufPtr)->len + SOS_MSG_CRC_SIZE)) &&
				(len <= I2C_MAX_MSG_LEN)) {

			// please do not edit the next line
			bufPtr = buff;
			// we have enough bytes for it to be a message, lets start the copy out
			// XXX msgPtr = (Message*)ker_malloc(sizeof(Message), I2C_PID);
			msgPtr = msg_create();
			if (msgPtr !=NULL) {
				uint8_t i=0;
				uint16_t runningCRC=0, crc_in=0;

				// extract the protocol field
				for (i=0; i<HDLC_PROTOCOL_SIZE; i++) {
					runningCRC = crcByte(runningCRC, bufPtr[i]);
				}

				// extract the header
				bufPtr = &buff[HDLC_PROTOCOL_SIZE];
				for (i=0; i<SOS_MSG_HEADER_SIZE; i++) {
					((uint8_t*)msgPtr)[i] = bufPtr[i];
					runningCRC = crcByte(runningCRC, bufPtr[i]);
				}

				// extract the data if it exists
				if (msgPtr->len != 0) {
					uint8_t *dataPtr;
					dataPtr = ker_malloc(((Message*)msgPtr)->len, I2C_PID);

					if (dataPtr != NULL) {

						msgPtr->data = dataPtr;

						bufPtr = &buff[HDLC_PROTOCOL_SIZE+SOS_MSG_HEADER_SIZE];
						for (i=0; i<msgPtr->len; i++) {
							msgPtr->data[i] = bufPtr[i];
							runningCRC = crcByte(runningCRC, bufPtr[i]);
						}
					} else { // -ENOMEM
						ker_free(msgPtr);
						goto post_error_msg;
					}
				} else {
					msgPtr->data = NULL;
				}

				// get the CRC and check it
				bufPtr = &buff[HDLC_PROTOCOL_SIZE+SOS_MSG_HEADER_SIZE+msgPtr->len];
				crc_in = bufPtr[0] | (bufPtr[1]<<8);

				if (crc_in == runningCRC) {
					// message passed all sanity checks including crc
					LED_DBG(LED_YELLOW_TOGGLE);
					if(msgPtr->data != NULL ) {
						msgPtr->flag = SOS_MSG_RELEASE;
					}
					handle_incoming_msg(msgPtr, SOS_MSG_I2C_IO);
					return;
				} else { // clean up
					ker_free(msgPtr->data);
					ker_free(msgPtr);
				}
			}
		}
	}

	// if we make it to here return error message
post_error_msg:
	post_short(
			i2c_sys.calling_mod_id,
			I2C_PID,
			MSG_ERROR,
			READ_ERROR,
			0,
			SOS_MSG_HIGH_PRIORITY);
}