コード例 #1
0
ssize_t LPC2000Serial::writeBlock(const void *buffer, size_t size, off_t where)
{
    Lock<FastMutex> l(txMutex);
    FastInterruptDisableLock dLock;
    size_t len=size;
    const char *buf=reinterpret_cast<const char*>(buffer);
    while(len>0)
    {
        //If no data in software and hardware queue
        if((serial->LSR & (1<<5)) && (txQueue.isEmpty()))
        {
            //Fill hardware queue first
            for(int i=0;i<hwTxQueueLen;i++)
            {
                serial->THR=*buf++;
                len--;
                if(len==0) break;
            }
        } else {
            if(txQueue.IRQput(*buf)==true)
            {
                buf++;
                len--;
            } else {
                FastInterruptEnableLock eLock(dLock);
                txQueue.waitUntilNotFull();
            }
        }
    }
    return size;
}
コード例 #2
0
/**
 * \internal
 * Read a single block of 512 bytes from an SD/MMC card.
 * Card must be selected prior to caling this function.
 * \param buffer, a buffer whose size is >=512 bytes
 * \param lba logical block address of the block to read.
 */
static bool singleBlockRead(unsigned char *buffer, unsigned int lba)
{
    if(cardType!=SDHC) lba*=512; // Convert to byte address if not SDHC

    if(waitForCardReady()==false) return false;

    // Single block read
    unsigned int* newBuf=BufferConverter::toWordAlignedWithoutCopy(buffer);
    CmdResult cr;
    DataResult dr;
    bool failed=true;
    for(;;)
    {
        // Since we read with polling, a context switch or interrupt here
        // would cause a fifo overrun, so we disable interrupts.
        FastInterruptDisableLock dLock;

        SDIO->DTIMER=1048576;
        SDIO->DLEN=512;
        //Block size 512 bytes, block data xfer, from card to controller
        SDIO->DCTRL=(9<<4) | SDIO_DCTRL_DTDIR | SDIO_DCTRL_DTEN;

        cr=Command::IRQsend(Command::CMD17,lba);
        if(cr.IRQvalidateR1Response())
        {
            dr=IRQreceiveDataBlock(newBuf,512/sizeof(unsigned int));
            SDIO->DCTRL=0; //Disable data path state machine
            
            //If failed because too slow check if it is possible to reduce speed
            if(dr.getError()==DataResult::RXOverrun)
            {
                if(ClockController::IRQreduceClockSpeed())
                {
                    //Disabling interrupts for too long is bad
                    FastInterruptEnableLock eLock(dLock);
                    //After an error during data xfer the card might be a little
                    //confused. So send STOP_TRANSMISSION command to reassure it
                    cr=Command::send(Command::CMD12,0);
                    if(cr.validateR1Response()) continue;
                }
            }

            if(dr.getError()==DataResult::Ok) failed=false;
        }
        break;
    }
    if(failed)
    {
        cr.validateR1Response();
        dr.validateError();
        //After an error during data xfer the card might be a little
        //confused. So send STOP_TRANSMISSION command to reassure it
        cr=Command::send(Command::CMD12,0);
        cr.validateR1Response();
        return false;
    }
    BufferConverter::toOriginalBuffer();
    return true;
}
コード例 #3
0
bool Thread::join(void** result)
{
    {
        FastInterruptDisableLock dLock;
        if(this==Thread::IRQgetCurrentThread()) return false;
        if(Thread::IRQexists(this)==false) return false;
        if(this->flags.isDetached()) return false;
        if(this->flags.isDeletedJoin()==false)
        {
            //Another thread already called join on toJoin
            if(this->joinData.waitingForJoin!=NULL) return false;

            this->joinData.waitingForJoin=Thread::IRQgetCurrentThread();
            for(;;)
            {
                //Wait
                Thread::IRQgetCurrentThread()->flags.IRQsetJoinWait(true);
                {
                    FastInterruptEnableLock eLock(dLock);
                    Thread::yield();
                }
                if(Thread::IRQexists(this)==false) return false;
                if(this->flags.isDetached()) return false;
                if(this->flags.isDeletedJoin()) break;
            }
        }
        //Thread deleted, complete join procedure
        //Setting detached flag will make isDeleted() return true,
        //so its memory can be deallocated
        this->flags.IRQsetDetached();
        if(result!=NULL) *result=this->joinData.result;
    }
    {
        PauseKernelLock lock;
        //Since there is surely one dead thread, deallocate it immediately
        //to free its memory as soon as possible
        Scheduler::PKremoveDeadThreads();
    }
    return true;
}
コード例 #4
0
/**
 * Used to initialize static objects only once, in a threadsafe way
 * \param g guard struct
 * \return 0 if object already initialized, 1 if this thread has to initialize
 * it, or lock if another thread has already started initializing it
 */
extern "C" int __cxa_guard_acquire(__guard *g)
{
    miosix::InterruptDisableLock dLock;
    volatile MiosixGuard *guard=reinterpret_cast<volatile MiosixGuard*>(g);
    for(;;)
    {
        if(guard->flag==1) return 0; //Object already initialized, good
        
        if(guard->flag==0)
        {
            //Object uninitialized, and no other thread trying to initialize it
            guard->owner=miosix::Thread::IRQgetCurrentThread();

            //guard->owner serves the double task of being the thread id of
            //the thread initializing the object, and being the flag to signal
            //that the object is initialized or not. If bit #0 of guard->owner
            //is @ 1 the object is initialized. All this works on the assumption
            //that Thread* pointers never have bit #0 @ 1, and this assetion
            //checks that this condition really holds
            if(guard->flag & 1) miosix::errorHandler(miosix::UNEXPECTED);
            return 1;
        }

        //If we get here, the object is being initialized by another thread
        if(guard->owner==miosix::Thread::IRQgetCurrentThread())
        {
            //Wait, the other thread initializing the object is this thread?!?
            //We have a recursive initialization error. Not throwing an
            //exception to avoid pulling in exceptions even with -fno-exception
            IRQerrorLog("Recursive initialization\r\n");
            _exit(1);
        }

        {
            miosix::InterruptEnableLock eLock(dLock);
            miosix::Thread::yield(); //Sort of a spinlock, a "yieldlock"...
        }
    }
}