TURAG-Feldbus
feldbus_base.h
1
233#ifndef TINA_FELDBUS_SLAVE_FELDBUS_H_
234#define TINA_FELDBUS_SLAVE_FELDBUS_H_
235
236
239
240#include "feldbus_config_check.h"
241
242
243
244#ifdef __cplusplus
245# include <cstdlib>
246# include <cstddef>
247# include <cstring>
248
249extern "C" {
250#else
251# include <stdlib.h>
252# include <string.h>
253# include <stdbool.h>
254#endif
255
256
257
258
264
268extern void turag_feldbus_hardware_init(void);
269
273extern void turag_feldbus_device_rts_off(void);
274
279extern void turag_feldbus_device_rts_on(void);
280
285extern void turag_feldbus_device_activate_dre_interrupt(void);
286
291extern void turag_feldbus_device_deactivate_dre_interrupt(void);
292
297extern void turag_feldbus_device_activate_rx_interrupt(void);
298
303extern void turag_feldbus_device_deactivate_rx_interrupt(void);
304
309extern void turag_feldbus_device_activate_tx_interrupt(void);
310
315extern void turag_feldbus_device_deactivate_tx_interrupt(void);
316
325extern void turag_feldbus_device_start_receive_timeout(void);
326
335extern void turag_feldbus_device_begin_interrupt_protect(void);
336
342extern void turag_feldbus_device_end_interrupt_protect(void);
343
352extern void turag_feldbus_device_toggle_led(void);
353
358extern void turag_feldbus_device_transmit_byte(uint8_t byte);
359
364extern void turag_feldbus_device_enable_bus_neighbours();
365
370extern void turag_feldbus_device_disable_bus_neighbours();
371
375extern void turag_feldbus_device_assert_low();
376
384extern void turag_feldbus_device_goto_sleep();
385
394extern void turag_feldbus_device_goto_deep_sleep();
395
401extern uint32_t turag_feldbus_device_get_static_storage_capacity();
402
408extern uint16_t turag_feldbus_device_get_static_storage_page_size();
409
419extern uint8_t turag_feldbus_device_read_from_static_storage(uint32_t offset, uint16_t size, uint8_t* buffer);
420
430extern uint8_t turag_feldbus_device_write_to_static_storage(uint32_t offset, const uint8_t* data, uint16_t size);
431
433
434
435
436
442
448static inline void turag_feldbus_device_byte_received(uint8_t data);
449
455static inline void turag_feldbus_device_ready_to_transmit(void);
456
462static inline void turag_feldbus_device_transmission_complete(void);
463
472static inline void turag_feldbus_device_receive_timeout_occured(void);
473
482#if defined(__DOXYGEN__)
483static inline void turag_feldbus_device_increase_uptime_counter(void);
484#endif
485
487
488
491#if defined(__DOXYGEN__)
492# define TURAG_FELDBUS_NO_ANSWER <configuration-dependend>
493#endif
494
498#if defined(__DOXYGEN__)
499typedef int FeldbusSize_t;
500#endif
501
503typedef uint8_t FeldbusAddress_t;
504
505
506
507
514
539typedef FeldbusSize_t (*TuragFeldbusPacketProcessor)(const uint8_t* message, FeldbusSize_t message_length, uint8_t* response);
540
541
556typedef void (*TuragFeldbusBroadcastProcessor)(const uint8_t* message, FeldbusSize_t message_length, uint8_t protocol_id);
558
559
560
561
562
568
576void turag_feldbus_device_init(
577 FeldbusAddress_t bus_address, uint32_t uuid,
578 const char* name, const char* version_info,
579 uint8_t device_protocol, uint8_t device_type,
580 TuragFeldbusPacketProcessor packetProcessor,
581 TuragFeldbusBroadcastProcessor broadcastProcessor);
582
583
584uint32_t turag_feldbus_device_hash_uuid(const uint8_t* key, size_t length);
585
591void turag_feldbus_do_processing(void);
592
593
595
596
597
598// debugging functions
599#if TURAG_FELDBUS_DEVICE_CONFIG_DEBUG_ENABLED || defined(__DOXYGEN__)
613 void print_text(const char*);
614
616 void print_char(uint8_t);
617
619 void print_short(uint16_t);
620
622 void print_sshort(int16_t x);
623
625 void print_long(uint32_t x);
626
628 void print_short_d(int16_t x);
629
631 void print_slong(int32_t);
632
634 void print_sshort_nn(int16_t x);
635
637 void print_short_nn(uint16_t x);
638
641 #define TURAG_FELDBUS_DEBUG_SAFE(function) function; while (turag_feldbus_device.transmission_active)
643#else
644# define print_text(x)
645# define print_char(x)
646# define print_short(x)
647# define print_sshort(x)
648# define print_long(x)
649# define print_short_d(x)
650# define print_slong(x)
651# define print_sshort_nn(x)
652# define print_short_nn(x)
653#endif
654
655#ifdef __cplusplus
656}
657#endif
658
659// hide some uninteresting stuff from documentation
660#if (!defined(__DOXYGEN__))
661
662#define TURAG_FELDBUS_DEVICE_ACTUAL_BUFFER_SIZE (TURAG_FELDBUS_DEVICE_CONFIG_BUFFER_SIZE + TURAG_FELDBUS_DEVICE_CONFIG_ADDRESS_LENGTH + TURAG_FELDBUS_DEVICE_CRC_SIZE)
663
664typedef struct {
665 // holds the number of bytes in txbuf
666 FeldbusSize_t transmitLength;
667 // offset in txbuf
668 FeldbusSize_t txOffset;
669 // offset in rxBuf
670 FeldbusSize_t rxOffset;
671 // if not 0, then there is a package waiting for processsing
672 volatile FeldbusSize_t rx_length;
673 // overflow detected
674 bool overflow;
675 // package loss detected and counter must be increased
676 bool package_lost_flag;
677 // overflow detected and counter must be increased
678 bool buffer_overflow_flag;
679#if TURAG_FELDBUS_DEVICE_CONFIG_DEBUG_ENABLED
680 volatile bool transmission_active;
681#endif
682 volatile bool toggleLedBlocked;
683 TuragFeldbusPacketProcessor packet_processor;
684 TuragFeldbusBroadcastProcessor broadcast_processor;
685 // bus address of the device
686 FeldbusAddress_t my_address;
687 const char* name;
688 size_t name_length;
689 const char* versioninfo;
690 size_t version_info_length;
691 uint8_t device_protocol;
692 uint8_t device_type;
693 uint32_t packagecount_correct;
694 uint32_t packagecount_buffer_overflow;
695 uint32_t packagecount_lost;
696 uint32_t packagecount_chksum_mismatch;
697 uint32_t uptime_counter;
698 // uuid of the device
699 uint8_t uuid[4] __attribute__((aligned(4)));
700 uint8_t txbuf[TURAG_FELDBUS_DEVICE_ACTUAL_BUFFER_SIZE] __attribute__((aligned(4)));
701 uint8_t rxbuf[TURAG_FELDBUS_DEVICE_ACTUAL_BUFFER_SIZE] __attribute__((aligned(4)));
702} turag_feldbus_device_t;
703
704
705extern turag_feldbus_device_t turag_feldbus_device;
706
707
708
709
710#endif // (!defined(__DOXYGEN__))
711
712
713#ifdef __cplusplus
714extern "C" {
715#endif
716
717static inline void turag_feldbus_device_byte_received(uint8_t data) {
718 // if at this point rx_length is not 0, obviously the last
719 // received package was not processed yet. This package
720 // will be overwritten now and is lost.
721 // Once rx_length is cleared, turag_feldbus_do_processing() will no longer
722 // try to copy packages from the in-buffer.
723 if (turag_feldbus_device.rx_length) {
724 turag_feldbus_device.rx_length = 0;
725 turag_feldbus_device.package_lost_flag = true;
726 }
727
728 // We need to check for overflow before actually storing the received
729 // byte. Otherwise we always get an overflow when the last byte in the
730 // buffer gets filled.
731 if (turag_feldbus_device.rxOffset >= TURAG_FELDBUS_DEVICE_ACTUAL_BUFFER_SIZE) {
732 turag_feldbus_device.rxOffset = 0;
733
734 // We have a buffer overflow. If this happens for the
735 // first time for this package, we check the address.
736 // If the package was for us, we increase the counter for
737 // package overflow.
738 if (!turag_feldbus_device.overflow) {
739 if (*((FeldbusAddress_t*)turag_feldbus_device.rxbuf) == turag_feldbus_device.my_address || *((FeldbusAddress_t*)turag_feldbus_device.rxbuf) == TURAG_FELDBUS_BROADCAST_ADDR)
740 {
741 turag_feldbus_device.buffer_overflow_flag = true;
742 }
743 turag_feldbus_device.overflow = true;
744 }
745 }
746
747 // accessing the buffer as an array is more effective than using a pointer
748 // and increasing it.
749 turag_feldbus_device.rxbuf[turag_feldbus_device.rxOffset] = data;
750 ++turag_feldbus_device.rxOffset;
751
752 // activate timer to recognize end of command
753 turag_feldbus_device_start_receive_timeout();
754}
755
756static inline void turag_feldbus_device_ready_to_transmit() {
757 // accessing the buffer as an array is more effective than using a pointer
758 // and increasing it.
759 turag_feldbus_device_transmit_byte(turag_feldbus_device.txbuf[turag_feldbus_device.txOffset]);
760 ++turag_feldbus_device.txOffset;
761
762 if (turag_feldbus_device.txOffset == turag_feldbus_device.transmitLength) {
763 turag_feldbus_device_deactivate_dre_interrupt();
764 turag_feldbus_device_activate_tx_interrupt();
765 }
766}
767
768static inline void turag_feldbus_device_transmission_complete() {
769 // turn off transmitter and release bus, turn on receiver
770 turag_feldbus_device_rts_off();
771 turag_feldbus_device_deactivate_tx_interrupt();
772 turag_feldbus_device_activate_rx_interrupt();
773
774#if TURAG_FELDBUS_DEVICE_CONFIG_DEBUG_ENABLED
775 turag_feldbus_device.transmission_active = false;
776#endif
777}
778
779
780static inline void turag_feldbus_device_receive_timeout_occured() {
781 if (turag_feldbus_device.package_lost_flag) {
782 ++turag_feldbus_device.packagecount_lost;
783 turag_feldbus_device.package_lost_flag = false;
784 }
785
786 if (turag_feldbus_device.buffer_overflow_flag) {
787 ++turag_feldbus_device.packagecount_buffer_overflow;
788 turag_feldbus_device.buffer_overflow_flag = false;
789 }
790
791 if ((*((FeldbusAddress_t*)turag_feldbus_device.rxbuf) == turag_feldbus_device.my_address || *((FeldbusAddress_t*)turag_feldbus_device.rxbuf) == TURAG_FELDBUS_BROADCAST_ADDR) &&
792 !turag_feldbus_device.overflow &&
793 turag_feldbus_device.rxOffset > 1)
794 {
795 // package ok -> signal main loop that we have package ready
796 turag_feldbus_device.rx_length = turag_feldbus_device.rxOffset;
797
798 // we stop the led blinking until the user program starts the package
799 // processing
800 turag_feldbus_device.toggleLedBlocked = true;
801 }
802
803 // reset rxOffset and overflow-flag to ensure correct
804 // receiving of future packages
805 turag_feldbus_device.rxOffset = 0;
806 turag_feldbus_device.overflow = 0;
807}
808
809static inline void turag_feldbus_device_increase_uptime_counter(void) {
810 ++turag_feldbus_device.uptime_counter;
811
812 // we only toggle the led if there is no package
813 // waiting to be processsed.
814 // We use this as an indicator for the user whether
815 // there is something wrong with the communication.
816 if (!turag_feldbus_device.toggleLedBlocked) {
817# if TURAG_FELDBUS_DEVICE_CONFIG_UPTIME_FREQUENCY >= 12
818# define COUNT_MAX (TURAG_FELDBUS_DEVICE_CONFIG_UPTIME_FREQUENCY / 12 - 1)
819# if COUNT_MAX > 255
820 static uint16_t count = 0;
821# else
822 static uint8_t count = 0;
823# endif
824 static uint8_t subcount = 0;
825
826 ++count;
827 if (count > COUNT_MAX) {
828 if (subcount == 0) {
829 turag_feldbus_device_toggle_led();
830 } else if (subcount == 1) {
831 turag_feldbus_device_toggle_led();
832 }
833 subcount = (subcount+1) & 7;
834 count = 0;
835 }
836# elif TURAG_FELDBUS_DEVICE_CONFIG_UPTIME_FREQUENCY >= 2
837 static uint8_t count = 0;
838
839 ++count;
840 if (count > (TURAG_FELDBUS_DEVICE_CONFIG_UPTIME_FREQUENCY / 2 - 1)) {
841 turag_feldbus_device_toggle_led();
842 count = 0;
843 }
844# else
845 turag_feldbus_device_toggle_led();
846# endif
847 }
848}
849
850
851
852#ifdef __cplusplus
853}
854#endif
855
856
857#endif /* TINA_FELDBUS_SLAVE_FELDBUS_H_ */
Functions and types for CRC checks.
#define TURAG_FELDBUS_DEVICE_CONFIG_UPTIME_FREQUENCY
Legt die Frequenz[Hz] fest, mit der turag_feldbus_slave_increase_uptime_counter() aufgerufen wird.
Definition: feldbus_config.h:71
struct __attribute__((packed))
Definition: feldbus_stellantriebe.h:76
Provides xor checksum calculation.