| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- * Copyright (C) 2004 by egnite Software GmbH. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- *
- */
- /*!
- * $Log$
- * Revision 1.7 2009/02/06 15:40:29 haraldkipp
- * Using newly available strdup() and calloc().
- * Replaced NutHeap routines by standard malloc/free.
- * Replaced pointer value 0 by NULL.
- *
- * Revision 1.6 2008/08/11 07:00:33 haraldkipp
- * BSD types replaced by stdint types (feature request #1282721).
- *
- * Revision 1.5 2008/02/15 17:08:05 haraldkipp
- * Calling the initialization routine more than once is now possible.
- * By default, half of the available memory will be allocated. Previous
- * versions eat all free memory but 8k.
- *
- * Revision 1.4 2007/04/12 09:08:57 haraldkipp
- * Segmented buffer routines ported to ARM.
- *
- * Revision 1.3 2004/12/17 15:28:33 haraldkipp
- * Bugfix. Comparison of the read and write pointers now includes the segments.
- * Thanks to Pete Allinson and Johan van der Stoel.
- *
- * Revision 1.2 2004/08/18 18:51:56 haraldkipp
- * Made banked memory configurable.
- *
- * Revision 1.1 2003/07/21 18:19:48 haraldkipp
- * First check in
- *
- */
- #include <sys/heap.h>
- #include <stdint.h>
- /*!
- * \addtogroup xgBankMem
- */
- /*@{*/
- #include <sys/bankmem.h>
- static char segbuf_empty;
- static uint32_t segbuf_total;
- static uint32_t segbuf_used;
- static char *segbuf_start;
- static char *segbuf_end;
- static char *segbuf_wp;
- static char segbuf_ws;
- static char *segbuf_rp;
- static char segbuf_rs;
- /*!
- * \brief Reset the segmented buffer.
- *
- * \return Pointer to the first buffer segment.
- */
- char *NutSegBufReset(void)
- {
- segbuf_rp = segbuf_wp = segbuf_start;
- segbuf_rs = segbuf_ws = 0;
- NutSegBufEnable(0);
- segbuf_empty = 1;
- segbuf_used = 0;
- return segbuf_start;
- }
- /*!
- * \brief Initialize the segmented buffer.
- *
- * \param size Number of bytes to allocate for the global buffer.
- * In systems with banked memory this parameter is
- * ignored and all banked memory is occupied for the
- * global buffer. In systems without banked memory,
- * the specified number of bytes is taken from heap
- * memory.
- *
- * \return Pointer to the first buffer segment or null on failures.
- */
- char *NutSegBufInit(size_t size)
- {
- #if NUTBANK_COUNT
- segbuf_start = (char *)(NUTBANK_START);
- segbuf_end = (char *)(NUTBANK_START) + NUTBANK_SIZE;
- segbuf_total = (uint32_t) NUTBANK_COUNT *(uint32_t) NUTBANK_SIZE;
- #else
- if (size == 0)
- size = NutHeapAvailable() / 2;
- if (segbuf_start) {
- NutHeapFree(segbuf_start);
- }
- if ((segbuf_start = NutHeapAlloc(size)) != NULL)
- segbuf_end = segbuf_start + size;
- segbuf_total = size;
- #endif
- return NutSegBufReset();
- }
- /*!
- * \brief Request segmented buffer space for writing.
- *
- * This call will also enable the current write segment and
- * may disable the current read segment.
- *
- * \param bcp Pointer to a variable, which receives the
- * number of consecutive bytes available for
- * writing.
- *
- * \return Pointer to the next write position.
- */
- char *NutSegBufWriteRequest(size_t * bcp)
- {
- if (segbuf_empty || segbuf_ws != segbuf_rs || segbuf_wp > segbuf_rp)
- *bcp = segbuf_end - segbuf_wp;
- else
- *bcp = segbuf_rp - segbuf_wp;
- NutSegBufEnable(segbuf_ws);
- return segbuf_wp;
- }
- /*!
- * \brief Request segmented buffer space for reading.
- *
- * This call will also enable the current read segment and
- * may disable the current write segment.
- *
- * \param bcp Pointer to a variable, which receives the
- * number of consecutive bytes available for
- * reading.
- *
- * \return Pointer to the next read position.
- */
- char *NutSegBufReadRequest(size_t * bcp)
- {
- if (segbuf_empty)
- *bcp = 0;
- else if (segbuf_ws != segbuf_rs || segbuf_rp >= segbuf_wp)
- *bcp = segbuf_end - segbuf_rp;
- else if ((*bcp = segbuf_wp - segbuf_rp) == 0 && segbuf_ws == segbuf_rs)
- segbuf_empty = 1;
- NutSegBufEnable(segbuf_rs);
- return segbuf_rp;
- }
- /*!
- * \brief Commit written buffer space.
- *
- * The write pointer will be incremented by the specified number of bytes.
- * If the pointer reaches the end of a segment, the next segment will be
- * enabled and the pointer will point to the start of the new segement.
- *
- * \param bc Number of bytes to commit.
- *
- * \return Pointer to the next write position.
- */
- char *NutSegBufWriteCommit(size_t bc)
- {
- if (bc) {
- segbuf_wp += bc;
- segbuf_empty = 0;
- segbuf_used += bc;
- if (segbuf_wp == segbuf_end) {
- segbuf_wp = segbuf_start;
- #if NUTBANK_COUNT > 0
- if (++segbuf_ws >= NUTBANK_COUNT)
- segbuf_ws = 0;
- #endif
- NutSegBufEnable(segbuf_ws);
- }
- }
- return segbuf_wp;
- }
- /*!
- * \brief Commit read buffer space.
- *
- * The read pointer will be incremented by the specified number of bytes.
- * If the pointer reaches the end of a segment, the next segment will be
- * enabled and the pointer will point to the start of the new segement.
- *
- * \param bc Number of bytes to commit.
- *
- * \return Pointer to the next read position.
- */
- char *NutSegBufReadCommit(size_t bc)
- {
- if (bc) {
- segbuf_rp += bc;
- segbuf_used -= bc;
- if (segbuf_rp == segbuf_end) {
- segbuf_rp = segbuf_start;
- #if NUTBANK_COUNT > 0
- if (++segbuf_rs >= NUTBANK_COUNT)
- segbuf_rs = 0;
- #endif
- NutSegBufEnable(segbuf_rs);
- }
- if (segbuf_rp == segbuf_wp && segbuf_rs == segbuf_ws)
- segbuf_empty = 1;
- }
- return segbuf_rp;
- }
- /*!
- * \brief Commit written buffer space and finish write access.
- *
- * The write pointer will be incremented by the specified number of bytes.
- * This call will also enable the current read segment and may disable the
- * current write segment.
- *
- * \param bc Number of bytes to commit.
- */
- void NutSegBufWriteLast(size_t bc)
- {
- if (bc) {
- segbuf_wp += bc;
- segbuf_used += bc;
- segbuf_empty = 0;
- if (segbuf_wp == segbuf_end) {
- segbuf_wp = segbuf_start;
- #if NUTBANK_COUNT > 0
- if (++segbuf_ws >= NUTBANK_COUNT)
- segbuf_ws = 0;
- #endif
- }
- }
- NutSegBufEnable(segbuf_rs);
- }
- /*!
- * \brief Commit written buffer space and finish read access.
- *
- * The write pointer will be incremented by the specified number of bytes.
- * This call will also enable the current read segment and may disable the
- * current write segment.
- *
- * \param bc Number of bytes to commit.
- */
- void NutSegBufReadLast(size_t bc)
- {
- if (bc) {
- segbuf_rp += bc;
- segbuf_used -= bc;
- if (segbuf_rp == segbuf_end) {
- segbuf_rp = segbuf_start;
- #if NUTBANK_COUNT > 0
- if (++segbuf_rs >= NUTBANK_COUNT)
- segbuf_rs = 0;
- #endif
- }
- if (segbuf_rp == segbuf_wp && segbuf_rs == segbuf_ws)
- segbuf_empty = 1;
- }
- NutSegBufEnable(segbuf_ws);
- }
- /*!
- * \brief Return the available buffer space.
- *
- * \return Total number of free bytes in the buffer.
- */
- uint32_t NutSegBufAvailable(void)
- {
- return segbuf_total - segbuf_used;
- }
- /*!
- * \brief Return the used buffer space.
- *
- * \return Total number of used bytes in the buffer.
- */
- uint32_t NutSegBufUsed(void)
- {
- return segbuf_used;
- }
- /*@}*/
|