B-MAC

B-MAC is a low-power listen CSMA (lpl-csma) protocol. More information can be found in the original B-MAC paper. The main idea about low-power-listen CSMA is that instead of leaving the receiver on 100% the radio is active for short bursts used to check for channel activity. If activity is detected, the radio remains on in order to receive the data. In order to ensure that a neighboring node receives the message, an extended preamble the length of the check interval is required.

There is a trade-off between checking more often or sending a longer preamble. For any particular sampling point (sensor sampling rate etc) there is an energy optimal checking rate.

Using the optimal radio checking rate derived from the best energy efficiency at a particular sampling point you can see the following life-time relationship.

The current Nano-RK implementation of BMAC has no internal transmit or receive buffers. Applications or higher level network layers must provide their own transmit and receive buffers. B-MAC will pass transmit buffers directly to the basic_rf transmit functions where additional information like a CRC checksum is added. When data is received, B-MAC will store this data in the last set receive buffer until the bmac_rx_release() function is called by a higher layer or application. The reception of a packet will generate a signal notifying any waiting tasks that the packet is ready. Received packets can be checked in a polling fashion using the bmac_rx_status() function, or a task can suspend until a packet arrives using the bmac_rx_packet_get() function. Timeouts on packet reception can be achieved using the wait until next wakeup configuration commands provided by Nano-RK. If a timeout occurs, bmac_wait_until_rx_packet() will return an error code. To allow efficient network layer development, the receive buffer can be changed using the bmac_rx_pkt_set_buffer() function. This should only be done after a packet is received or at startup. If a new receive buffer pointer has been set, it is then safe to call bmac_rx_pkt_release() indicating that the B-MAC task is allowed to buffer new packets at that memory location.

The application or network layer is required to allocate static buffers. These should typically be globally defined at the top of your application:

1   uint8_t tx_buf[RF_MAX_PAYLOAD_SIZE];
2   uint8_t rx_buf[RF_MAX_PAYLOAD_SIZE];

Here is a sample of how you initialize BMAC and receive data (found in the basic_bmac sample project):

 1void rx_task()
 2{
 3  uint8_t i,len;
 4  int8_t rssi,val;
 5  uint8_t *local_rx_buf;
 6
 7  printf( "rx_task PID=%d\r\n",nrk_get_pid());
 8
 9  // init bmac on channel 25 
10  bmac_init(25);
11  // This sets the next RX buffer.
12  // This can be called at anytime before releaseing the packet
13  // if you wish to do a zero-copy buffer switch
14  bmac_rx_pkt_set_buffer(rx_buf,RF_MAX_PAYLOAD_SIZE);
15
16  while(1)
17    {
18    // Wait until an RX packet is received
19    val=bmac_wait_until_rx_packet();    
20    // Get the RX packet 
21      nrk_set_led(BLUE_LED); 
22    local_rx_buf=bmac_rx_pkt_get(&len,&rssi);
23    printf( "Got RX packet len=%d RSSI=%d [",len,rssi );
24        for(i=0; i<len; i++ )
25                   printf( "%c", local_rx_buf[i]);
26        printf( "]\r\n" );
27    // Release the RX buffer so future packets can arrive 
28      nrk_clr_led(BLUE_LED); 
29    bmac_rx_pkt_release();
30    }
31
32}

Here is an example of how you would transmit data using BMAC:

 1void tx_task()
 2{
 3  uint8_t j, i,val,len,cnt;
 4
 5  printf( "tx_task PID=%d\r\n",nrk_get_pid());
 6
 7  // Wait until the tx_task starts up bmac
 8  // This should be called by all tasks using bmac that
 9  // do not call bmac_init()...
10  while(!bmac_started()) nrk_wait_until_next_period();
11  cnt=0;
12  while(1)
13    {
14    // Build a TX packet
15    sprintf( tx_buf, "This is a test %d",cnt );
16    cnt++;
17    // Transmit the packet 
18      nrk_set_led(ORANGE_LED); 
19    val=bmac_tx_packet(tx_buf, strlen(tx_buf));
20    // Task gets control again after TX complete
21      nrk_clr_led(ORANGE_LED); 
22    printf( "TX task sent data!\r\n" );
23    nrk_wait_until_next_period();
24    }
25
26}

For more detailed information see the bmac-api.

chk_vs_life.png (62.1 kB) Anthony Rowe, 03/04/2007 08:03 pm

chk_vs_sample.png (42.4 kB) Anthony Rowe, 03/04/2007 08:03 pm

rx_tx.png (13 kB) Anthony Rowe, 03/05/2007 03:15 pm