A copy of the mbed USBDevice with USBSerial library

Dependents:   STM32L0_LoRa Smartage STM32L0_LoRa Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Thu Feb 22 12:18:45 2018 +0100
Revision:
3:bddd92cd3a17
Child:
4:b6be2a43cb85
Added a buffered USB serial which allows to print on interrupts

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>
Helmut Tschemernjak 3:bddd92cd3a17 9 // #include "arch.h"
Helmut Tschemernjak 3:bddd92cd3a17 10
Helmut Tschemernjak 3:bddd92cd3a17 11 #ifdef FEATURE_USBSERIAL
Helmut Tschemernjak 3:bddd92cd3a17 12
Helmut Tschemernjak 3:bddd92cd3a17 13 #include "USBSerial.h"
Helmut Tschemernjak 3:bddd92cd3a17 14 #include "USBSerialBuffered.h"
Helmut Tschemernjak 3:bddd92cd3a17 15
Helmut Tschemernjak 3:bddd92cd3a17 16 USBSerialBuffered::USBSerialBuffered(int MaxBuffSize, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect_blocking)
Helmut Tschemernjak 3:bddd92cd3a17 17 : USBSerial(vendor_id, product_id, product_release, connect_blocking)
Helmut Tschemernjak 3:bddd92cd3a17 18 , mFullBuffSize(MaxBuffSize)
Helmut Tschemernjak 3:bddd92cd3a17 19 {
Helmut Tschemernjak 3:bddd92cd3a17 20 ASSERT(mFullBuffSize > CorkBuffSize && "FullBuff must be larger than CorkBuff");
Helmut Tschemernjak 3:bddd92cd3a17 21 m_buff = new char[mFullBuffSize];
Helmut Tschemernjak 3:bddd92cd3a17 22 m_irq_buffused = 0;
Helmut Tschemernjak 3:bddd92cd3a17 23 POISONMEM(m_buff, mFullBuffSize);
Helmut Tschemernjak 3:bddd92cd3a17 24 }
Helmut Tschemernjak 3:bddd92cd3a17 25
Helmut Tschemernjak 3:bddd92cd3a17 26 USBSerialBuffered::~USBSerialBuffered() {
Helmut Tschemernjak 3:bddd92cd3a17 27 delete[] m_buff;
Helmut Tschemernjak 3:bddd92cd3a17 28 }
Helmut Tschemernjak 3:bddd92cd3a17 29
Helmut Tschemernjak 3:bddd92cd3a17 30 //-----------------------------------------------------------------------------
Helmut Tschemernjak 3:bddd92cd3a17 31
Helmut Tschemernjak 3:bddd92cd3a17 32 int USBSerialBuffered::irqbuff_acquire() {
Helmut Tschemernjak 3:bddd92cd3a17 33 core_util_critical_section_enter();
Helmut Tschemernjak 3:bddd92cd3a17 34 return help_atomic_load_relaxed(&m_irq_buffused);
Helmut Tschemernjak 3:bddd92cd3a17 35 }
Helmut Tschemernjak 3:bddd92cd3a17 36
Helmut Tschemernjak 3:bddd92cd3a17 37 void USBSerialBuffered::irqbuff_release(int buffused) {
Helmut Tschemernjak 3:bddd92cd3a17 38 help_atomic_store_relaxed(&m_irq_buffused, buffused);
Helmut Tschemernjak 3:bddd92cd3a17 39 irq_barrier();
Helmut Tschemernjak 3:bddd92cd3a17 40 core_util_critical_section_exit();
Helmut Tschemernjak 3:bddd92cd3a17 41 }
Helmut Tschemernjak 3:bddd92cd3a17 42
Helmut Tschemernjak 3:bddd92cd3a17 43 //-----------------------------------------------------------------------------
Helmut Tschemernjak 3:bddd92cd3a17 44
Helmut Tschemernjak 3:bddd92cd3a17 45 int USBSerialBuffered::printf_irqsafe(const char *fmt, ...) {
Helmut Tschemernjak 3:bddd92cd3a17 46 std::va_list va;
Helmut Tschemernjak 3:bddd92cd3a17 47 va_start(va, fmt);
Helmut Tschemernjak 3:bddd92cd3a17 48 int nchars = vprintf_irqsafe(fmt, va);
Helmut Tschemernjak 3:bddd92cd3a17 49 va_end(va);
Helmut Tschemernjak 3:bddd92cd3a17 50 return nchars;
Helmut Tschemernjak 3:bddd92cd3a17 51 }
Helmut Tschemernjak 3:bddd92cd3a17 52
Helmut Tschemernjak 3:bddd92cd3a17 53 int USBSerialBuffered::vprintf_irqsafe(const char *fmt, std::va_list va) {
Helmut Tschemernjak 3:bddd92cd3a17 54 if (RunningInInterrupt()) {
Helmut Tschemernjak 3:bddd92cd3a17 55 int buffused = irqbuff_acquire();
Helmut Tschemernjak 3:bddd92cd3a17 56 int bspc = mFullBuffSize - buffused;
Helmut Tschemernjak 3:bddd92cd3a17 57 ASSERT(bspc >= 0);
Helmut Tschemernjak 3:bddd92cd3a17 58 int nchars = vsnprintf(m_buff + buffused, bspc, fmt, va);
Helmut Tschemernjak 3:bddd92cd3a17 59 if (nchars >= bspc) {
Helmut Tschemernjak 3:bddd92cd3a17 60 memcpy(m_buff + mFullBuffSize - 4, "...\n", 4);
Helmut Tschemernjak 3:bddd92cd3a17 61 buffused = mFullBuffSize;
Helmut Tschemernjak 3:bddd92cd3a17 62 } else {
Helmut Tschemernjak 3:bddd92cd3a17 63 buffused += nchars;
Helmut Tschemernjak 3:bddd92cd3a17 64 }
Helmut Tschemernjak 3:bddd92cd3a17 65 irqbuff_release(buffused);
Helmut Tschemernjak 3:bddd92cd3a17 66 return nchars;
Helmut Tschemernjak 3:bddd92cd3a17 67 } else {
Helmut Tschemernjak 3:bddd92cd3a17 68 return USBSerial::vprintf(fmt, va);
Helmut Tschemernjak 3:bddd92cd3a17 69 }
Helmut Tschemernjak 3:bddd92cd3a17 70 }
Helmut Tschemernjak 3:bddd92cd3a17 71
Helmut Tschemernjak 3:bddd92cd3a17 72 //-----------------------------------------------------------------------------
Helmut Tschemernjak 3:bddd92cd3a17 73
Helmut Tschemernjak 3:bddd92cd3a17 74 void USBSerialBuffered::flush() {
Helmut Tschemernjak 3:bddd92cd3a17 75 int flushedbytes = 0;
Helmut Tschemernjak 3:bddd92cd3a17 76 int buffused = 0;
Helmut Tschemernjak 3:bddd92cd3a17 77 while (1) {
Helmut Tschemernjak 3:bddd92cd3a17 78 bool wasequal = help_atomic_compare_and_swap(&m_irq_buffused, buffused, 0);
Helmut Tschemernjak 3:bddd92cd3a17 79 if (wasequal)
Helmut Tschemernjak 3:bddd92cd3a17 80 break;
Helmut Tschemernjak 3:bddd92cd3a17 81 //
Helmut Tschemernjak 3:bddd92cd3a17 82 // This only works because @ref print_irq always _increases_ @c m_irq_buffused (but never(!) decreases this variable)
Helmut Tschemernjak 3:bddd92cd3a17 83 //
Helmut Tschemernjak 3:bddd92cd3a17 84 buffused = help_atomic_load_relaxed(&m_irq_buffused); // __sync_* implementation requires this refetch
Helmut Tschemernjak 3:bddd92cd3a17 85 while (buffused != flushedbytes) {
Helmut Tschemernjak 3:bddd92cd3a17 86 int towrite = std::min(buffused - flushedbytes, static_cast<int>(CorkBuffSize));
Helmut Tschemernjak 3:bddd92cd3a17 87 if (connected()) {
Helmut Tschemernjak 3:bddd92cd3a17 88 writeBlock(reinterpret_cast<uint8_t *>(m_buff + flushedbytes), towrite);
Helmut Tschemernjak 3:bddd92cd3a17 89 }
Helmut Tschemernjak 3:bddd92cd3a17 90 flushedbytes += towrite;
Helmut Tschemernjak 3:bddd92cd3a17 91 }
Helmut Tschemernjak 3:bddd92cd3a17 92 }
Helmut Tschemernjak 3:bddd92cd3a17 93 }
Helmut Tschemernjak 3:bddd92cd3a17 94
Helmut Tschemernjak 3:bddd92cd3a17 95 void USBSerialBuffered::putc_normal(int c) {
Helmut Tschemernjak 3:bddd92cd3a17 96 while (1) {
Helmut Tschemernjak 3:bddd92cd3a17 97 int buffused = help_atomic_load_relaxed(&m_irq_buffused);
Helmut Tschemernjak 3:bddd92cd3a17 98 if (buffused >= CorkBuffSize) {
Helmut Tschemernjak 3:bddd92cd3a17 99 flush();
Helmut Tschemernjak 3:bddd92cd3a17 100 } else {
Helmut Tschemernjak 3:bddd92cd3a17 101 // static bool TESTonce;
Helmut Tschemernjak 3:bddd92cd3a17 102 // if (! TESTonce) {
Helmut Tschemernjak 3:bddd92cd3a17 103 // printf_irqsafe("ppp");
Helmut Tschemernjak 3:bddd92cd3a17 104 // TESTonce = true;
Helmut Tschemernjak 3:bddd92cd3a17 105 // }
Helmut Tschemernjak 3:bddd92cd3a17 106 ASSERT(buffused + 1 <= CorkBuffSize);
Helmut Tschemernjak 3:bddd92cd3a17 107 bool wasequal = help_atomic_compare_and_swap(&m_irq_buffused, buffused, buffused + 1);
Helmut Tschemernjak 3:bddd92cd3a17 108 if (wasequal) {
Helmut Tschemernjak 3:bddd92cd3a17 109 m_buff[buffused] = c; // alloc successful
Helmut Tschemernjak 3:bddd92cd3a17 110 return;
Helmut Tschemernjak 3:bddd92cd3a17 111 } else {
Helmut Tschemernjak 3:bddd92cd3a17 112 // An irq extended m_irq_buffused, start over
Helmut Tschemernjak 3:bddd92cd3a17 113 }
Helmut Tschemernjak 3:bddd92cd3a17 114 }
Helmut Tschemernjak 3:bddd92cd3a17 115 }
Helmut Tschemernjak 3:bddd92cd3a17 116 }
Helmut Tschemernjak 3:bddd92cd3a17 117
Helmut Tschemernjak 3:bddd92cd3a17 118 int USBSerialBuffered::_putc(int c) {
Helmut Tschemernjak 3:bddd92cd3a17 119 putc_normal(c);
Helmut Tschemernjak 3:bddd92cd3a17 120 if (c == '\n') {
Helmut Tschemernjak 3:bddd92cd3a17 121 flush();
Helmut Tschemernjak 3:bddd92cd3a17 122 }
Helmut Tschemernjak 3:bddd92cd3a17 123 return connected() ? 1 : 0;
Helmut Tschemernjak 3:bddd92cd3a17 124 }
Helmut Tschemernjak 3:bddd92cd3a17 125
Helmut Tschemernjak 3:bddd92cd3a17 126 #endif