A copy of the mbed USBDevice with USBSerial library

Dependents:   STM32L0_LoRa Smartage STM32L0_LoRa Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Sun Feb 24 14:52:33 2019 +0100
Revision:
8:961423d1da74
Parent:
4:b6be2a43cb85
Added sleep manager support to avoids sleeps while a USB CDC
connection is active

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Helmut Tschemernjak 3:bddd92cd3a17 1 /*
Helmut Tschemernjak 3:bddd92cd3a17 2 * $Id: bulkserial.h,v 1.3 2018/02/23 15:04:29 grimrath Exp $
Helmut Tschemernjak 3:bddd92cd3a17 3 * This is an unpublished work copyright (c) 2017 HELIOS Software GmbH
Helmut Tschemernjak 3:bddd92cd3a17 4 * 30827 Garbsen, Germany
Helmut Tschemernjak 3:bddd92cd3a17 5 */
Helmut Tschemernjak 3:bddd92cd3a17 6
Helmut Tschemernjak 3:bddd92cd3a17 7 #include <algorithm>
Helmut Tschemernjak 3:bddd92cd3a17 8 #include <mbed.h>
Helmut64 4:b6be2a43cb85 9 #include "PinMap.h"
Helmut Tschemernjak 3:bddd92cd3a17 10
Helmut Tschemernjak 3:bddd92cd3a17 11 #ifdef FEATURE_USBSERIAL
Helmut Tschemernjak 3:bddd92cd3a17 12 #include "USBSerial.h"
Helmut Tschemernjak 3:bddd92cd3a17 13 #include "USBSerialBuffered.h"
Helmut Tschemernjak 3:bddd92cd3a17 14
Helmut64 4:b6be2a43cb85 15 #ifndef ASSERT
Helmut64 4:b6be2a43cb85 16 #define ASSERT MBED_ASSERT
Helmut64 4:b6be2a43cb85 17 #endif
Helmut64 4:b6be2a43cb85 18 #ifndef POISONMEM
Helmut64 4:b6be2a43cb85 19 static inline void POISONMEM(void *ptr, size_t sz) {
Helmut64 4:b6be2a43cb85 20 memset(ptr, 0x55, sz);
Helmut64 4:b6be2a43cb85 21 }
Helmut64 4:b6be2a43cb85 22 #endif
Helmut64 4:b6be2a43cb85 23 #if defined(__ATOMIC_RELAXED)
Helmut64 4:b6be2a43cb85 24
Helmut64 4:b6be2a43cb85 25 #define help_atomic_load_relaxed(ptr) __atomic_load_n((ptr), __ATOMIC_RELAXED)
Helmut64 4:b6be2a43cb85 26
Helmut64 4:b6be2a43cb85 27 #define help_atomic_store_relaxed(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELAXED)
Helmut64 4:b6be2a43cb85 28
Helmut64 4:b6be2a43cb85 29 #define help_atomic_readclr_relaxed(ptr) __atomic_exchange_n((ptr), 0, __ATOMIC_RELAXED)
Helmut64 4:b6be2a43cb85 30
Helmut64 4:b6be2a43cb85 31 #define help_atomic_or_relaxed(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_RELAXED)
Helmut64 4:b6be2a43cb85 32
Helmut64 4:b6be2a43cb85 33 #ifdef __cplusplus
Helmut64 4:b6be2a43cb85 34 template<typename T> inline bool help_atomic_compare_and_swap(T *ptr, T checkval, T newval) {
Helmut64 4:b6be2a43cb85 35 return __atomic_compare_exchange_n(ptr, &checkval, newval, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
Helmut64 4:b6be2a43cb85 36 }
Helmut64 4:b6be2a43cb85 37 #else
Helmut64 4:b6be2a43cb85 38 #define help_atomic_compare_and_swap(ptr, checkval, newval) __sync_bool_compare_and_swap((ptr), (checkval), (newval))
Helmut64 4:b6be2a43cb85 39 #endif
Helmut64 4:b6be2a43cb85 40
Helmut64 4:b6be2a43cb85 41 #define sync_memory(mem) do { \
Helmut64 4:b6be2a43cb85 42 asm volatile("" : "=m" (mem)); \
Helmut64 4:b6be2a43cb85 43 __atomic_thread_fence(__ATOMIC_SEQ_CST); \
Helmut64 4:b6be2a43cb85 44 } while (0)
Helmut64 4:b6be2a43cb85 45
Helmut64 4:b6be2a43cb85 46 #define irq_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)
Helmut64 4:b6be2a43cb85 47
Helmut64 4:b6be2a43cb85 48 #define sync_memory_all() do { \
Helmut64 4:b6be2a43cb85 49 asm volatile("" : : : "memory"); \
Helmut64 4:b6be2a43cb85 50 __atomic_thread_fence(__ATOMIC_SEQ_CST); \
Helmut64 4:b6be2a43cb85 51 } while (0)
Helmut64 4:b6be2a43cb85 52
Helmut64 4:b6be2a43cb85 53 #else // defined(__ATOMIC_RELAXED)
Helmut64 4:b6be2a43cb85 54
Helmut64 4:b6be2a43cb85 55 #define help_atomic_load_relaxed(ptr) (*(ptr))
Helmut64 4:b6be2a43cb85 56
Helmut64 4:b6be2a43cb85 57 #define help_atomic_store_relaxed(ptr, val) ((void)(*(ptr) = (val)))
Helmut64 4:b6be2a43cb85 58
Helmut64 4:b6be2a43cb85 59 #define help_atomic_readclr_relaxed(ptr) __sync_fetch_and_and((ptr), 0)
Helmut64 4:b6be2a43cb85 60
Helmut64 4:b6be2a43cb85 61 #define help_atomic_or_relaxed(ptr, val) __sync_fetch_and_or((ptr), (val))
Helmut64 4:b6be2a43cb85 62
Helmut64 4:b6be2a43cb85 63 #define help_atomic_compare_and_swap(ptr, checkval, newval) __sync_bool_compare_and_swap((ptr), (checkval), (newval))
Helmut64 4:b6be2a43cb85 64
Helmut64 4:b6be2a43cb85 65 #define sync_memory(mem) __sync_synchronize()
Helmut64 4:b6be2a43cb85 66
Helmut64 4:b6be2a43cb85 67 #define sync_memory_all() __sync_synchronize()
Helmut64 4:b6be2a43cb85 68
Helmut64 4:b6be2a43cb85 69 #define irq_barrier() __sync_synchronize()
Helmut64 4:b6be2a43cb85 70
Helmut64 4:b6be2a43cb85 71 #endif
Helmut64 4:b6be2a43cb85 72
Helmut64 4:b6be2a43cb85 73
Helmut Tschemernjak 3:bddd92cd3a17 74 USBSerialBuffered::USBSerialBuffered(int MaxBuffSize, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking)
Helmut Tschemernjak 3:bddd92cd3a17 75 : USBSerial(vendor_id, product_id, product_release, connect_blocking)
Helmut Tschemernjak 3:bddd92cd3a17 76 , mFullBuffSize(MaxBuffSize)
Helmut Tschemernjak 3:bddd92cd3a17 77 {
Helmut Tschemernjak 3:bddd92cd3a17 78 ASSERT(mFullBuffSize > CorkBuffSize && "FullBuff must be larger than CorkBuff");
Helmut Tschemernjak 3:bddd92cd3a17 79 m_buff = new char[mFullBuffSize];
Helmut Tschemernjak 3:bddd92cd3a17 80 m_irq_buffused = 0;
Helmut Tschemernjak 3:bddd92cd3a17 81 POISONMEM(m_buff, mFullBuffSize);
Helmut Tschemernjak 3:bddd92cd3a17 82 }
Helmut Tschemernjak 3:bddd92cd3a17 83
Helmut Tschemernjak 3:bddd92cd3a17 84 USBSerialBuffered::~USBSerialBuffered() {
Helmut Tschemernjak 3:bddd92cd3a17 85 delete[] m_buff;
Helmut Tschemernjak 3:bddd92cd3a17 86 }
Helmut Tschemernjak 3:bddd92cd3a17 87
Helmut Tschemernjak 3:bddd92cd3a17 88 //-----------------------------------------------------------------------------
Helmut Tschemernjak 3:bddd92cd3a17 89
Helmut Tschemernjak 3:bddd92cd3a17 90 int USBSerialBuffered::irqbuff_acquire() {
Helmut Tschemernjak 3:bddd92cd3a17 91 core_util_critical_section_enter();
Helmut Tschemernjak 3:bddd92cd3a17 92 return help_atomic_load_relaxed(&m_irq_buffused);
Helmut Tschemernjak 3:bddd92cd3a17 93 }
Helmut Tschemernjak 3:bddd92cd3a17 94
Helmut Tschemernjak 3:bddd92cd3a17 95 void USBSerialBuffered::irqbuff_release(int buffused) {
Helmut Tschemernjak 3:bddd92cd3a17 96 help_atomic_store_relaxed(&m_irq_buffused, buffused);
Helmut Tschemernjak 3:bddd92cd3a17 97 irq_barrier();
Helmut Tschemernjak 3:bddd92cd3a17 98 core_util_critical_section_exit();
Helmut Tschemernjak 3:bddd92cd3a17 99 }
Helmut Tschemernjak 3:bddd92cd3a17 100
Helmut Tschemernjak 3:bddd92cd3a17 101 //-----------------------------------------------------------------------------
Helmut Tschemernjak 3:bddd92cd3a17 102
Helmut Tschemernjak 3:bddd92cd3a17 103 int USBSerialBuffered::printf_irqsafe(const char *fmt, ...) {
Helmut Tschemernjak 3:bddd92cd3a17 104 std::va_list va;
Helmut Tschemernjak 3:bddd92cd3a17 105 va_start(va, fmt);
Helmut Tschemernjak 3:bddd92cd3a17 106 int nchars = vprintf_irqsafe(fmt, va);
Helmut Tschemernjak 3:bddd92cd3a17 107 va_end(va);
Helmut Tschemernjak 3:bddd92cd3a17 108 return nchars;
Helmut Tschemernjak 3:bddd92cd3a17 109 }
Helmut Tschemernjak 3:bddd92cd3a17 110
Helmut Tschemernjak 3:bddd92cd3a17 111 int USBSerialBuffered::vprintf_irqsafe(const char *fmt, std::va_list va) {
Helmut Tschemernjak 3:bddd92cd3a17 112 if (RunningInInterrupt()) {
Helmut Tschemernjak 3:bddd92cd3a17 113 int buffused = irqbuff_acquire();
Helmut Tschemernjak 3:bddd92cd3a17 114 int bspc = mFullBuffSize - buffused;
Helmut Tschemernjak 3:bddd92cd3a17 115 ASSERT(bspc >= 0);
Helmut Tschemernjak 3:bddd92cd3a17 116 int nchars = vsnprintf(m_buff + buffused, bspc, fmt, va);
Helmut Tschemernjak 3:bddd92cd3a17 117 if (nchars >= bspc) {
Helmut Tschemernjak 3:bddd92cd3a17 118 memcpy(m_buff + mFullBuffSize - 4, "...\n", 4);
Helmut Tschemernjak 3:bddd92cd3a17 119 buffused = mFullBuffSize;
Helmut Tschemernjak 3:bddd92cd3a17 120 } else {
Helmut Tschemernjak 3:bddd92cd3a17 121 buffused += nchars;
Helmut Tschemernjak 3:bddd92cd3a17 122 }
Helmut Tschemernjak 3:bddd92cd3a17 123 irqbuff_release(buffused);
Helmut Tschemernjak 3:bddd92cd3a17 124 return nchars;
Helmut Tschemernjak 3:bddd92cd3a17 125 } else {
Helmut Tschemernjak 3:bddd92cd3a17 126 return USBSerial::vprintf(fmt, va);
Helmut Tschemernjak 3:bddd92cd3a17 127 }
Helmut Tschemernjak 3:bddd92cd3a17 128 }
Helmut Tschemernjak 3:bddd92cd3a17 129
Helmut Tschemernjak 3:bddd92cd3a17 130 //-----------------------------------------------------------------------------
Helmut Tschemernjak 3:bddd92cd3a17 131
Helmut Tschemernjak 3:bddd92cd3a17 132 void USBSerialBuffered::flush() {
Helmut Tschemernjak 3:bddd92cd3a17 133 int flushedbytes = 0;
Helmut Tschemernjak 3:bddd92cd3a17 134 int buffused = 0;
Helmut Tschemernjak 3:bddd92cd3a17 135 while (1) {
Helmut Tschemernjak 3:bddd92cd3a17 136 bool wasequal = help_atomic_compare_and_swap(&m_irq_buffused, buffused, 0);
Helmut Tschemernjak 3:bddd92cd3a17 137 if (wasequal)
Helmut Tschemernjak 3:bddd92cd3a17 138 break;
Helmut Tschemernjak 3:bddd92cd3a17 139 //
Helmut Tschemernjak 3:bddd92cd3a17 140 // This only works because @ref print_irq always _increases_ @c m_irq_buffused (but never(!) decreases this variable)
Helmut Tschemernjak 3:bddd92cd3a17 141 //
Helmut Tschemernjak 3:bddd92cd3a17 142 buffused = help_atomic_load_relaxed(&m_irq_buffused); // __sync_* implementation requires this refetch
Helmut Tschemernjak 3:bddd92cd3a17 143 while (buffused != flushedbytes) {
Helmut Tschemernjak 3:bddd92cd3a17 144 int towrite = std::min(buffused - flushedbytes, static_cast<int>(CorkBuffSize));
Helmut Tschemernjak 3:bddd92cd3a17 145 if (connected()) {
Helmut Tschemernjak 3:bddd92cd3a17 146 writeBlock(reinterpret_cast<uint8_t *>(m_buff + flushedbytes), towrite);
Helmut Tschemernjak 3:bddd92cd3a17 147 }
Helmut Tschemernjak 3:bddd92cd3a17 148 flushedbytes += towrite;
Helmut Tschemernjak 3:bddd92cd3a17 149 }
Helmut Tschemernjak 3:bddd92cd3a17 150 }
Helmut Tschemernjak 3:bddd92cd3a17 151 }
Helmut Tschemernjak 3:bddd92cd3a17 152
Helmut Tschemernjak 3:bddd92cd3a17 153 void USBSerialBuffered::putc_normal(int c) {
Helmut Tschemernjak 3:bddd92cd3a17 154 while (1) {
Helmut Tschemernjak 3:bddd92cd3a17 155 int buffused = help_atomic_load_relaxed(&m_irq_buffused);
Helmut Tschemernjak 3:bddd92cd3a17 156 if (buffused >= CorkBuffSize) {
Helmut Tschemernjak 3:bddd92cd3a17 157 flush();
Helmut Tschemernjak 3:bddd92cd3a17 158 } else {
Helmut Tschemernjak 3:bddd92cd3a17 159 // static bool TESTonce;
Helmut Tschemernjak 3:bddd92cd3a17 160 // if (! TESTonce) {
Helmut Tschemernjak 3:bddd92cd3a17 161 // printf_irqsafe("ppp");
Helmut Tschemernjak 3:bddd92cd3a17 162 // TESTonce = true;
Helmut Tschemernjak 3:bddd92cd3a17 163 // }
Helmut Tschemernjak 3:bddd92cd3a17 164 ASSERT(buffused + 1 <= CorkBuffSize);
Helmut Tschemernjak 3:bddd92cd3a17 165 bool wasequal = help_atomic_compare_and_swap(&m_irq_buffused, buffused, buffused + 1);
Helmut Tschemernjak 3:bddd92cd3a17 166 if (wasequal) {
Helmut Tschemernjak 3:bddd92cd3a17 167 m_buff[buffused] = c; // alloc successful
Helmut Tschemernjak 3:bddd92cd3a17 168 return;
Helmut Tschemernjak 3:bddd92cd3a17 169 } else {
Helmut Tschemernjak 3:bddd92cd3a17 170 // An irq extended m_irq_buffused, start over
Helmut Tschemernjak 3:bddd92cd3a17 171 }
Helmut Tschemernjak 3:bddd92cd3a17 172 }
Helmut Tschemernjak 3:bddd92cd3a17 173 }
Helmut Tschemernjak 3:bddd92cd3a17 174 }
Helmut Tschemernjak 3:bddd92cd3a17 175
Helmut Tschemernjak 3:bddd92cd3a17 176 int USBSerialBuffered::_putc(int c) {
Helmut Tschemernjak 3:bddd92cd3a17 177 putc_normal(c);
Helmut Tschemernjak 3:bddd92cd3a17 178 if (c == '\n') {
Helmut Tschemernjak 3:bddd92cd3a17 179 flush();
Helmut Tschemernjak 3:bddd92cd3a17 180 }
Helmut Tschemernjak 3:bddd92cd3a17 181 return connected() ? 1 : 0;
Helmut Tschemernjak 3:bddd92cd3a17 182 }
Helmut Tschemernjak 3:bddd92cd3a17 183
Helmut Tschemernjak 3:bddd92cd3a17 184 #endif