Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
USBSerialStream.cpp
00001 /* USBSerialStream.cpp */ 00002 /* 00003 Copyright (C) 2012 ARM Limited. 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy of 00006 this software and associated documentation files (the "Software"), to deal in 00007 the Software without restriction, including without limitation the rights to 00008 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 00009 of the Software, and to permit persons to whom the Software is furnished to do 00010 so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in all 00013 copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00021 SOFTWARE. 00022 */ 00023 00024 #define __DEBUG__ 0 //Maximum verbosity 00025 #ifndef __MODULE__ 00026 #define __MODULE__ "USBSerialStream.cpp" 00027 #endif 00028 00029 #include "core/fwk.h" 00030 00031 #include <stdio.h> 00032 00033 #include "USBSerialStream.h" 00034 00035 00036 USBSerialStream::USBSerialStream(IUSBHostSerial& serial) : m_serial(serial), m_serialTxFifoEmpty(true), 00037 m_availableSphre(1), m_spaceSphre(1), m_inBuf() 00038 { 00039 m_availableSphre.wait(); 00040 m_spaceSphre.wait(); 00041 //Attach interrupts 00042 m_serial.attach(this); 00043 } 00044 00045 /*virtual*/ USBSerialStream::~USBSerialStream() 00046 { 00047 m_serial.attach(NULL); 00048 } 00049 00050 //0 for non-blocking (returns immediately), -1 for infinite blocking 00051 /*virtual*/ int USBSerialStream::read(uint8_t* buf, size_t* pLength, size_t maxLength, uint32_t timeout/*=osWaitForever*/) 00052 { 00053 DBG("Trying to read at most %d chars", maxLength); 00054 int ret = waitAvailable(timeout); 00055 if(ret) 00056 { 00057 WARN("Error %d while waiting for incoming data", ret); 00058 return ret; 00059 } 00060 int readLen = MIN( available(), maxLength ); 00061 *pLength = readLen; 00062 00063 setupReadableISR(false); 00064 while(readLen--) 00065 { 00066 m_inBuf.dequeue(buf); 00067 buf++; 00068 } 00069 setupReadableISR(true); 00070 DBG("Read %d chars successfully", *pLength); 00071 return OK; 00072 } 00073 00074 /*virtual*/ size_t USBSerialStream::available() 00075 { 00076 setupReadableISR(false); //m_inBuf.available() is not reentrant 00077 size_t len = m_inBuf.available(); 00078 setupReadableISR(true); 00079 return len; 00080 } 00081 00082 /*virtual*/ int USBSerialStream::waitAvailable(uint32_t timeout/*=osWaitForever*/) //Wait for data to be available 00083 { 00084 int ret; 00085 if(available()) //Is data already available? 00086 { 00087 m_availableSphre.wait(0); //Clear the queue as data is available 00088 return OK; 00089 } 00090 00091 DBG("Waiting for data availability %d ms (-1 is infinite)", timeout); 00092 ret = m_availableSphre.wait(timeout); //Wait for data to arrive or for abort 00093 if(ret <= 0) 00094 { 00095 DBG("Timeout"); 00096 return NET_TIMEOUT; 00097 } 00098 if(!m_inBuf.available()) //Even if abort has been called, return that data is available 00099 { 00100 DBG("Aborted"); 00101 return NET_INTERRUPTED; 00102 } 00103 DBG("Finished waiting"); 00104 m_availableSphre.wait(0); //Clear the queue as data is available 00105 return OK; 00106 } 00107 00108 /*virtual*/ int USBSerialStream::abortRead() //Abort current reading (or waiting) operation 00109 { 00110 if( /*!available()*/true ) //If there is data pending, no need to abort 00111 { 00112 m_availableSphre.release(); //Force exiting the waiting state 00113 } 00114 else 00115 { 00116 DBG("Serial is readable"); ; 00117 } 00118 return OK; 00119 } 00120 00121 void USBSerialStream::setupReadableISR(bool en) 00122 { 00123 m_serial.setupIrq(en, IUSBHostSerial::RxIrq); 00124 } 00125 00126 void USBSerialStream::readable() //Callback from m_serial when new data is available 00127 { 00128 while(m_serial.readable()) 00129 { 00130 m_inBuf.queue(m_serial.getc()); 00131 } 00132 m_serial.readPacket(); //Start read of next packet 00133 m_availableSphre.release(); //Force exiting the waiting state 00134 } 00135 00136 //0 for non-blocking (returns immediately), -1 for infinite blocking 00137 /*virtual*/ int USBSerialStream::write(uint8_t* buf, size_t length, uint32_t timeout/*=-1*/) 00138 { 00139 DBG("Trying to write %d chars", length); 00140 do 00141 { 00142 int ret = waitSpace(timeout); 00143 if(ret) 00144 { 00145 WARN("Error %d while waiting for space"); 00146 return ret; 00147 } 00148 int writeLen = MIN( space(), length ); 00149 DBG("Writing %d chars", length); 00150 setupWriteableISR(false); 00151 while(writeLen) 00152 { 00153 m_outBuf.queue(*buf); 00154 buf++; 00155 length--; 00156 writeLen--; 00157 } 00158 setupWriteableISR(true); 00159 } while(length); 00160 //If m_serial tx fifo is empty we need to start the packet write 00161 setupWriteableISR(false); 00162 if( m_outBuf.available() && m_serialTxFifoEmpty ) 00163 { 00164 writeable(); 00165 } 00166 setupWriteableISR(true); 00167 DBG("Write successful"); 00168 return OK; 00169 } 00170 00171 /*virtual*/ size_t USBSerialStream::space() 00172 { 00173 setupWriteableISR(false); //m_outBuf.available() is not reentrant 00174 size_t len = CIRCBUF_SIZE - m_outBuf.available(); 00175 setupWriteableISR(true); 00176 return len; 00177 } 00178 00179 /*virtual*/ int USBSerialStream::waitSpace(uint32_t timeout/*=-1*/) //Wait for space to be available 00180 { 00181 int ret; 00182 if(space()) //Is still space already left? 00183 { 00184 m_spaceSphre.wait(0); //Clear the queue as space is available 00185 return OK; 00186 } 00187 00188 DBG("Waiting for data space %d ms (-1 is infinite)", timeout); 00189 ret = m_spaceSphre.wait(timeout); //Wait for space to be made or for abort 00190 if(ret <= 0) 00191 { 00192 DBG("Timeout"); 00193 return NET_TIMEOUT; 00194 } 00195 if(!space()) //Even if abort has been called, return that space is available 00196 { 00197 DBG("Aborted"); 00198 return NET_INTERRUPTED; 00199 } 00200 m_spaceSphre.wait(0); //Clear the queue as space is available 00201 return OK; 00202 } 00203 00204 /*virtual*/ int USBSerialStream::abortWrite() //Abort current writing (or waiting) operation 00205 { 00206 if( !space() ) //If there is space left, no need to abort 00207 { 00208 m_spaceSphre.release(); //Force exiting the waiting state 00209 } 00210 return OK; 00211 } 00212 00213 void USBSerialStream::setupWriteableISR(bool en) 00214 { 00215 m_serial.setupIrq(en, IUSBHostSerial::TxIrq); 00216 } 00217 00218 void USBSerialStream::writeable() //Callback from m_serial when new space is available 00219 { 00220 if(m_outBuf.isEmpty()) 00221 { 00222 m_serialTxFifoEmpty = true; 00223 } 00224 else 00225 { 00226 m_serialTxFifoEmpty = false; 00227 while(m_serial.writeable() && !m_outBuf.isEmpty()) 00228 { 00229 uint8_t c; 00230 m_outBuf.dequeue(&c); 00231 m_serial.putc((char)c); 00232 } 00233 static volatile int i=0; 00234 m_serial.writePacket(); //Start packet write 00235 } 00236 m_spaceSphre.release(); //Force exiting the waiting state 00237 }
Generated on Tue Jul 12 2022 17:50:57 by
