EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

BestComm Tasks for PSC1 Rx on MPC5200B

Started by Taran March 5, 2007
Hi,

I am using the MPC5200B processor, the Lite5200B evaluation Board. I
have a Rx BestComm Task for receivng data on PSC1 (Uart Mode) from the
Hyperterminal of the host desktop. For downloading the executable I am
using the Windriver ICE, Vision Click. Compiler is diab.

When I set up the Rx Task and start it and then send a text file
through the Hyperterminal I get BestComm interrupts and the whole file
is taken from Rx FIFO and placed into the local buffer that I specify.

Rx BD Task configuration:
 - rx_setup.NumBD = 3;
 - rx_setup.Size.MaxBuf = 512;
 - rx_setup.Initiator = INITIATOR_PSC1_RX;
 - rx_setup.StartAddrSrc = PSC1_RX_FIFO_ADDRESS;
 - rx_setup.SzSrc = SZ_UINT32;
 - rx_setup.SzDst = SZ_UINT32;
 - rx_setup.IncrDst = 4;

where rx_setup is a var of type TaskSetupParamSet_t.

Task used is tasksetup_gen_rx_bd_0 provided in the BestComm image
'image_rtos_3'

Now the problem.

When the Rx FIFO alarm value is set to (512 - 0x8) or a similar high
value the Rx FIFO data is copied to the local buffer. But this would
mean that I would get a BestComm interrupt whenever there are 8 bytes
in the Rx FIFO, not a very promising situation as I'd be only handling
the interrupts. If I change the Rx FIFO alarm value to something like
0x30 or 0xF0 (interrupt when these many bytes of free space is there
in the Rx FIFO), the BestComm fails to copy 16 bytes of incoming data
after every 32 bytes. This is consistent over a file transfer of 18kb
file. The values of Rx FIFO alarm I have given here were found after
lots of trial and error to figure out where the file is received in
its entirety. The granularity level if seems is don't care here as it
has not affect on the behaviour of the Rx Task.

Following is the Code snippet for BestComm initialization and BestComm
interrupt handler:

// BestComm specific inclusion, all have C-Style linkages
extern "C" {
#include "bestcomm_api.h"
#include "mpc5200.h"
#include "sdma.h"
#include "int_ctrl.h"
}


/* Begin BestComm specific global vars. */
/* Memory Base Address Register */
#define MBAR 0xF0000000

/* SDMA Task Bar Register */
#define SDMA_REG_OFFSET 0x1200

/* SRAM Module */
#define SRAM_OFFSET 0x8000

PSCUart the_uart(1, 115200, 66000000, 8, PSC::noparity, PSC::PT_0,
0x7, (void *)MBAR);

/* Tx and Rx FIFO are double buffered and share the same address
 * writes always happen at Tx FIFO and reads always happen
 * from Rx FIFO
*/

/* RX FIFO */
#define PSC1_RX_FIFO_ADDRESS (MBAR + 0x200C)

// Start BestComm specific global vars.
TaskSetupParamSet_t tx_setup, rx_setup;
TaskId tx_task_id, rx_task_id;


Uint32 buff_size = 512; // size of the buffer
Uint32 frags = 1536/buff_size; // how many BDs do we use
Uint8 test_array[18*1024]; // an 18Kb array to hold the file
static Uint8 index=0;
Uint8 *tx_rx_phys_data = test_array;
BDIdx rx_next_bd;

sdma_regs *sdma;
int_ctrl_regs *int_ctrl;

// End BestComm specific global vars.

void BestComm_interrupt(INT vector_number)
{
   static BDIdx bdi=0;
   if(TaskIntStatus( rx_task_id ) == rx_task_id )
   {
 		/*
   	 * Clear the task interrupt.
   	 */
      TaskIntClear( rx_task_id );

      TaskBD1_t *bd;

         /*
   		 * Get a pointer to the next buffer to be release tracked by
          * the bdi static variable.
   		 */
   		bd = (TaskBD1_t*)TaskGetBD(rx_task_id,bdi);

         /* Release as many buffer as possible.
          *
         */
         while( !(bd->Status & SDMA_BD_MASK_READY))
         {
            /* Handle the packet*/
            bdi = TaskBDRelease(rx_task_id);
            /* One buffer full of data received, assign it to the
transmit task*/
            rx_next_bd = TaskBDAssign(rx_task_id,
                                      ( tx_rx_phys_data + (buff_size *
index++)),
                                      NULL, (int)buff_size,0);
            bd = (TaskBD1_t*)TaskGetBD(rx_task_id,bdi);
         }
	 }
   #endif
}


// forward declaration for function which initialized the BestComm
// Initialized the Task API, Loads The Task Image, Sets up the task,
// Assigns the Buffer Descriptors, and finally starts the Task.

// compile only when in buffer descriptor mode.
void initialize_BestComm_buffer_descriptor_tx_rx()
{
   int_ctrl = (int_ctrl_regs *)(MBAR + MBAR_INT_CTRL);

   int_ctrl->pimsk &= (~(PIMSK_BESTCOMM));

   /*
    *  Setup the Source pointer
   */
   for (int i = 0; i < 512; i++)
     test_array[i] = 'A';
   for (int i = 512; i < 1024; i++)
     test_array[i] = 'B';
   for (int i = 1024; i < 1536; i++)
     test_array[i] = 'C';
   for (int i = 1024; i < sizeof(test_array)/sizeof(test_array[0]); i+
+)
     test_array[i] = 'Z';

  /*
   * The API needs to be initialized before any other calls.
   * This needs to be passed the value of MBAR for the MPC5200.
  */
  TasksInitAPI((Uint8 *) MBAR);

  /*
   * Somewhere before task_setup, the load task should be called
   * with the sdma register location after the taskbar has been
   * loaded with the destination address of the task image. In
   * this instance, the address is the beginning of SRAM.
   */
  sdma = (sdma_regs *)(MBAR + SDMA_REG_OFFSET);
  sdma->taskBar = MBAR + SRAM_OFFSET;

  TasksLoadImage(sdma);

  /*Set up the PSC Transmit task descriptor*/
  rx_setup.NumBD = frags;
  rx_setup.Size.MaxBuf = buff_size;
  rx_setup.Initiator = INITIATOR_PSC1_RX;
  rx_setup.StartAddrSrc = PSC1_RX_FIFO_ADDRESS;
  rx_setup.SzSrc = SZ_UINT32;
  rx_setup.SzDst = SZ_UINT32;
  rx_setup.IncrDst = 4;

  /*
   * Now the rx task can be setup using TaskSetup.
  */
  rx_task_id = TaskSetup( TASK_GEN_RX_BD_1, &rx_setup );

  /* Assign the three buffers for receiving data
   * Assume that three buffers worth of data are ready to receive,
   * so TaskBDAssign is used to describe them. Store the first buffer
   * descriptor index to retire.
  */

  for(Uint8 i=0; i <frags; i++)
  {
     rx_next_bd = TaskBDAssign(rx_task_id,tx_rx_phys_data +
((buff_size)*index++),
                            NULL, (int)buff_size,0);
  }



  // set RX FIFO Alarm, interrupt when only 8 bytes are filled
  *reinterpret_cast<Uint16*> (MBAR + 0x2000 + 0x6E) = 0x30;
  // set the Rx FIFO Granularity for alarm to disappear (when 512 - 7)
bytes
  // of space is free in the FIFO
  *reinterpret_cast<Uint8*> (MBAR + 0x2000 + 0x68) |= 0x4;

  // Disable Prefetch: set to 1 to disable prefetch on CommBus
  // Set the PE Bit in the SDMA Interrupt Vector, PTD Control Register
  //*reinterpret_cast<Uint32*>(MBAR + 0x1210) |= 0x01; // Do we really
need this?

   /*
   * Enable tasks
  */
  TaskStart(rx_task_id, TASK_AUTOSTART_ENABLE, rx_task_id,
TASK_INTERRUPT_ENABLE);
}

Also do we really need to disable the Prefetch? AFAIK there isn't any
relationship mentioned in the User Manual about any dependency of
Alarm value on Granularity or vice versa. The sample code given by
them does not set the Alarm and Granularity values and does not
disable the Prefetch. These values are the default value whatever they
may be (this data is not provided in the sample code).

Any pointers or help or suggestions would be appreciated.
Thanks in advance.

Regards,
Taran


The 2024 Embedded Online Conference