Esempio n. 1
0
inline void hal_set_rst_low()
{
#if (RF230_BUS == 1)
  gpio_output_clear(GPIOA, 8);
#else
  gpio_output_clear(GPIOB, 10);
#endif
}
Esempio n. 2
0
// Initialize TX/RX state
void init_tx_rx_state(void) {
    _tx_pin.port_index = GPIO_PORT_C;
    _tx_pin.pin_index = GPIO_PIN_19;
    _rx_pin.port_index = GPIO_PORT_B;
    _rx_pin.pin_index = GPIO_PIN_13;
    
    gpio_mux_configure(_tx_pin, GPIO_MUX_OUTPUT);
    gpio_mux_configure(_rx_pin, GPIO_MUX_OUTPUT);

    // By default, RX = always on and TX = enabled on demand
    gpio_output_clear(_tx_pin);
    gpio_output_clear(_rx_pin);
    
    log_debug("RS485: Initialized RS485 TX/RX state");
}
Esempio n. 3
0
// Send Modbus packet
int send_modbus_packet(uint8_t device_address, uint8_t sequence_number, Packet* packet_to_send) {
    int bytes_written = 0;
    uint16_t packet_crc16 = 0;
    uint8_t crc16_first_byte_index = 0;
    int packet_size = packet_to_send->header.length + MODBUS_PACKET_OVERHEAD;
    uint8_t modbus_packet[packet_size];
    
    //printf(">>>>>>>>>>>>>>>>>>>>> SEN %llu\n", microseconds());
    
    // Assemble Modbus packet header    
    modbus_packet[0] = device_address;
    modbus_packet[1] = RS485_EXTENSION_MODBUS_FUNCTION_CODE;
    modbus_packet[2] = sequence_number;
    
    // Assemble Tinkerforge packet header
    memcpy(&modbus_packet[3], &packet_to_send->header, sizeof(PacketHeader));
    
    // Assemble Tinkerforge packet payload (if any)
    memcpy(&modbus_packet[3+sizeof(PacketHeader)], &packet_to_send->payload,
           packet_to_send->header.length - TINKERFORGE_HEADER_LENGTH);

    // Calculating CRC16
    packet_crc16 = crc16(modbus_packet, packet_to_send->header.length + MODBUS_PACKET_HEADER_LENGTH);
    
    // Assemble the calculated CRC16 to the Modbus packet
    crc16_first_byte_index = packet_to_send->header.length +
                             MODBUS_PACKET_HEADER_LENGTH;
    modbus_packet[crc16_first_byte_index] = packet_crc16 >> 8;
    modbus_packet[++crc16_first_byte_index] = packet_crc16 & 0x00FF;

    // Enabling TX
    start = microseconds();
    gpio_output_set(_tx_pin);
    
    // Sending packet
    bytes_written = write(_rs485_serial_fd, modbus_packet, sizeof(modbus_packet));
    
    if (bytes_written <= 0) {
        // Disabling TX
        gpio_output_clear(_tx_pin);
        end = microseconds();
        send_verify_flag = 0;
        log_error("RS485: Error sending packet through serial interface");
        return -1;
    }

    // Save the packet as byte array
    memcpy(current_request_as_byte_array, modbus_packet, packet_size);

    // Start the send verify timer
    setup_timer(&send_verify_timer, TIME_UNIT_NSEC, SEND_VERIFY_TIMEOUT);
    timerfd_settime(_send_verify_event, 0, &send_verify_timer, NULL);
    
    // Set send verify flag
    send_verify_flag = 1;
    
    log_debug("RS485: Packet sent through serial interface");
    
    return bytes_written;
}
Esempio n. 4
0
static void red_extension_configure_pin(ExtensionPinConfiguration *config, int extension) {
	gpio_mux_configure(config->pin[extension], config->mux);

	if (config->value == 0) {
		gpio_output_clear(config->pin[extension]);
	} else {
		gpio_output_set(config->pin[extension]); // This should enable pull-up in case of input
	}
}
Esempio n. 5
0
static void spi_radio_cs(uint8_t hi) {
#if (RF230_BUS == 1)
  if (hi) {
    gpio_output_set(GPIOA, 4);
  } else {
    gpio_output_clear(GPIOA, 4);
  }
#else
#endif
}
Esempio n. 6
0
// Resets stack
static void red_stack_reset(void) {
	// Change mux of reset pin to output
	gpio_mux_configure(_red_stack_reset_stack_pin, GPIO_MUX_OUTPUT);

	gpio_output_clear(_red_stack_reset_stack_pin);
	SLEEP_NS(0, 1000*1000*100); // Clear reset pin for 100ms to force reset
	gpio_output_set(_red_stack_reset_stack_pin);
	SLEEP_NS(1, 1000*1000*500); // Wait 1.5s so slaves can start properly

	// Change mux back to interrupt, so we can see if a human presses reset
	gpio_mux_configure(_red_stack_reset_stack_pin, GPIO_MUX_6);
}
Esempio n. 7
0
// Send verify timeout event handler
void send_verify_timeout_handler(void *opaque) {
	(void)opaque;

    // Disabling TX
    gpio_output_clear(_tx_pin);
    end = microseconds();
    // Disabling timers
    disable_all_timers();
    // Clearing send verify flag
    send_verify_flag = 0;
    sent_ack_of_data_packet = 0;
    // Start slave poll timer in case of master
    if(_modbus_serial_config_address == 0 ) {
        master_current_request_processed = 1;
        master_poll_slave_timeout_handler(NULL);
    }
    log_error("RS485: Error sending packet on serial interface");
}
Esempio n. 8
0
// Master retry event handler
void master_retry_timeout_handler(void* opaque) {
	(void)opaque;

    // Turning off the timers
    disable_all_timers();
    
    if(master_current_retry <= 0) {
        if(send_verify_flag) {
            // Disabling TX
            gpio_output_clear(_tx_pin);
            end = microseconds();
            // Clearing send verify flag
            send_verify_flag = 0;
        }
        if(sent_current_request_from_queue) {
            queue_pop(&_rs485_extension.packet_to_modbus_queue, NULL);
            sent_current_request_from_queue = 0;
        }
        partial_receive_flag = 0;
        master_current_request_processed = 1;
        master_poll_slave_timeout_handler(NULL);
        return;
    }

    // Resend request    
    partial_receive_flag = 0;
    master_current_request_processed = 0;
    send_modbus_packet(_rs485_extension.slaves[master_current_slave_to_process],
                       current_sequence_number,
                       &current_request);
    
    log_debug("RS485: Retrying to send current request");
    
    // Decrease current retry
    master_current_retry --;
    
    // Start master retry timer
    setup_timer(&master_retry_timer, TIME_UNIT_NSEC, MASTER_RETRY_TIMEOUT);
    timerfd_settime(_master_retry_event, 0, &master_retry_timer, NULL);
}
Esempio n. 9
0
// New data available event handler
void rs485_serial_data_available_handler(void* opaque) {
	(void)opaque;

    if(!send_verify_flag) {
        disable_all_timers();
    }

    int bytes_received = 0;
    uint32_t uid_from_packet = 0;
    int add_recipient_opaque;
    Packet empty_packet;
    Packet data_packet;
    uint64_t dummy_read_buffer;
    
    // Merge or simply save the received bytes
    if(partial_receive_flag) {
        bytes_received = read(_rs485_serial_fd,
                              &receive_buffer[partial_receive_merge_index],
                              (RECEIVE_BUFFER_SIZE - partial_receive_merge_index));

        
        printf("bytes_received %d\n", bytes_received);

        partial_receive_merge_index = partial_receive_merge_index + bytes_received;
    }
    else {
        partial_receive_merge_index = read(_rs485_serial_fd, receive_buffer, RECEIVE_BUFFER_SIZE);

    if (partial_receive_merge_index != 13)
        printf("partial_receive_merge_index %d\n", partial_receive_merge_index);
    }
    //log_info("PARTIAL_RECEIVE_MERGE_INDEX = %d", partial_receive_merge_index);
    // Checks at least 13 bytes is available in the receive buffer
    if(partial_receive_merge_index >= 13) {
        int packet_validation_code =
        is_valid_packet(receive_buffer, partial_receive_merge_index);
        
        switch(packet_validation_code) {
            case PACKET_SEND_VERIFY_OK:
                // Stop send verify timer
                if (read(_send_verify_event, &dummy_read_buffer, sizeof(uint64_t))) {}
                setup_timer(&send_verify_timer, TIME_UNIT_NSEC, 0);
                timerfd_settime(_send_verify_event, 0, &send_verify_timer, NULL);
                // Disabling TX
                gpio_output_clear(_tx_pin);
                end = microseconds();
                // Clearing send verify flag
                send_verify_flag = 0;
                // Clearing partial receive flag
                partial_receive_flag = 0;
                
                if(sent_ack_of_data_packet) {
                    sent_ack_of_data_packet = 0;
                    master_current_request_processed = 1;
                    master_poll_slave_timeout_handler(NULL);
                }
                log_debug("RS485: Send verified");
                return;
            
            case PACKET_EMPTY_OK:
                // Proper empty packet
                log_debug("RS485: Empty packet received");
                
                if(sent_current_request_from_queue){
                    queue_pop(&_rs485_extension.packet_to_modbus_queue, NULL);
                    sent_current_request_from_queue = 0;
                }
                // Updating recipient in the routing table
                memcpy(&uid_from_packet, &receive_buffer[3], sizeof(uint32_t));
                stack_add_recipient(&_rs485_extension.base, uid_from_packet, receive_buffer[0]);
                
                partial_receive_flag = 0;
                master_current_request_processed = 1;
                if(sent_ack_of_data_packet) {
                    sent_ack_of_data_packet = 0;
                }
                master_poll_slave_timeout_handler(NULL);
                return;
            
            case PACKET_DATA_OK:
                // Proper data packet
                log_info("RS485: Data packet received");
                
                // Send message into brickd dispatcher
                memset(&data_packet, 0, sizeof(Packet));
                memcpy(&data_packet, &receive_buffer[3], partial_receive_merge_index - MODBUS_PACKET_OVERHEAD);
                network_dispatch_response(&data_packet);
                log_debug("RS485: Dispatched packet to network subsystem");
                
                if(sent_current_request_from_queue){
                    queue_pop(&_rs485_extension.packet_to_modbus_queue, NULL);
                    sent_current_request_from_queue = 0;
                }
                
                // Updating recipient in the routing table
                memcpy(&uid_from_packet, &receive_buffer[3], sizeof(uint32_t));
                add_recipient_opaque = receive_buffer[0];
                stack_add_recipient(&_rs485_extension.base, uid_from_packet, add_recipient_opaque);
                
                // Send ACK to the slave
                memset(&empty_packet, 0, sizeof(PacketHeader));
                empty_packet.header.length = 8;
                send_modbus_packet(_rs485_extension.slaves[master_current_slave_to_process],
                                   current_sequence_number,
                                   &empty_packet);
                sent_ack_of_data_packet = 1;
                return;
            
            case PACKET_ERROR_SEND_VERIFY:
                // Retry the current request
                log_error("RS485: Send verify failed");
                partial_receive_flag = 0;
                master_current_retry = MASTER_RETRIES;
                master_retry_timeout_handler(NULL);
                return;
                
            case PACKET_ERROR_ADDRESS:
                // Retry the current request
                log_error("RS485: Wrong address in packet");
                partial_receive_flag = 0;
                master_current_retry = MASTER_RETRIES;
                master_retry_timeout_handler(NULL);
                return;
                
            case PACKET_ERROR_FUNCTION_CODE:
                log_error("RS485: Wrong function code in packet");
                partial_receive_flag = 0;
                master_current_retry = MASTER_RETRIES;
                master_retry_timeout_handler(NULL);
                return;
                
            case PACKET_ERROR_SEQUENCE_NUMBER:
                // Retry the current request
                log_info("RS485: Wrong sequence number in packet");
                partial_receive_flag = 0;
                master_current_retry = MASTER_RETRIES;
                master_retry_timeout_handler(NULL);
                return;
                
            case PACKET_ERROR_LENGTH:
                // Retry the current request
                log_error("RS485: Wrong length in packet");
                partial_receive_flag = 0;
                master_current_retry = MASTER_RETRIES;
                master_retry_timeout_handler(NULL);
                return;
            
            case PACKET_ERROR_LENGTH_PARTIAL:
                log_debug("RS485: Partial data packet recieved");
                handle_partial_receive();
                return;
            
            case PACKET_ERROR_CRC16:
                // Retry the current request
                log_error("RS485: Wrong CRC16 in packet");
                partial_receive_flag = 0;
                master_current_retry = MASTER_RETRIES;
                master_retry_timeout_handler(NULL);
                return;
            
            default:
                return;
        }
    }
    else {
        log_debug("RS485: Partial packet recieved");
        handle_partial_receive();
        return;
    }
    if(send_verify_flag) {
        // Disabling TX
        gpio_output_clear(_tx_pin);
        end = microseconds();
        // Stop send verify timer
        if (read(_send_verify_event, &dummy_read_buffer, sizeof(uint64_t))) {}
        setup_timer(&send_verify_timer, TIME_UNIT_NSEC, 0);
        timerfd_settime(_send_verify_event, 0, &send_verify_timer, NULL);
        // Clearing send verify flag
        send_verify_flag = 0;
    }
    abort_current_request();
    return;
}
Esempio n. 10
0
void api_led_on ( )
{
	gpio_output_clear ( GPIO_LED );
}
Esempio n. 11
0
static int red_stack_init_spi(void) {
	uint8_t slave;
	const uint8_t mode = RED_STACK_SPI_CONFIG_MODE;
	const uint8_t lsb_first = RED_STACK_SPI_CONFIG_LSB_FIRST;
	const uint8_t bits_per_word = RED_STACK_SPI_CONFIG_BITS_PER_WORD;
	const uint32_t max_speed_hz = RED_STACK_SPI_CONFIG_MAX_SPEED_HZ;

	// Set Master High pin to low (so Master Bricks above RED Brick can
	// configure themselves as slave)
	gpio_mux_configure(_red_stack_master_high_pin, GPIO_MUX_OUTPUT);
	gpio_output_clear(_red_stack_master_high_pin);

	// Initialize slaves
	for (slave = 0; slave < RED_STACK_SPI_MAX_SLAVES; slave++) {
		_red_stack.slaves[slave].stack_address = slave;
		_red_stack.slaves[slave].status = RED_STACK_SLAVE_STATUS_ABSENT;
		_red_stack.slaves[slave].slave_select_pin = _red_stack_slave_select_pins[slave];
		_red_stack.slaves[slave].sequence_number_master = 1;
		_red_stack.slaves[slave].sequence_number_slave = 0;

		// Bring slave in initial state (deselected)
		gpio_mux_configure(_red_stack.slaves[slave].slave_select_pin, GPIO_MUX_OUTPUT);
		red_stack_spi_deselect(&_red_stack.slaves[slave]);
	}

	// Reset slaves and wait for slaves to be ready
	red_stack_reset();

	// Open spidev
	_red_stack_spi_fd = open(_red_stack_spi_device, O_RDWR);
	if (_red_stack_spi_fd < 0) {
		log_error("Could not open %s", _red_stack_spi_device);
		return -1;
	}

	if (ioctl(_red_stack_spi_fd, SPI_IOC_WR_MODE, &mode) < 0) {
		log_error("Could not configure SPI mode");
		return -1;
	}

	if (ioctl(_red_stack_spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed_hz) < 0) {
		log_error("Could not configure SPI max speed");
		return -1;
	}

	if (ioctl(_red_stack_spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits_per_word) < 0) {
		log_error("Could not configure SPI bits per word");
		return -1;
	}

	if (ioctl(_red_stack_spi_fd, SPI_IOC_WR_LSB_FIRST, &lsb_first) < 0) {
		log_error("Could not configure SPI lsb first");
		return -1;
	}

	// Create SPI packet transceive thread
	// FIXME: maybe handshake thread start?
	thread_create(&_red_stack_spi_thread, red_stack_spi_thread, NULL);

	return 0;
}
Esempio n. 12
0
static void red_stack_spi_select(REDStackSlave *slave) {
	gpio_output_clear(slave->slave_select_pin);
}