diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c
index f7ea7304e43d90913e99bf206bedfee563b94503..fbff9bf94be1ac58b8e9c616c4792d27eb523f21 100644
--- a/common/utils/nr/nr_common.c
+++ b/common/utils/nr/nr_common.c
@@ -1011,6 +1011,8 @@ bool nr_timer_tick(NR_timer_t *timer)
   bool expired = false;
   if (timer->active) {
     timer->counter += timer->step;
+    if (timer->target == UINT_MAX) // infinite target, never expires
+      return false;
     expired = nr_timer_expired(*timer);
     if (expired)
       timer->active = false;
@@ -1020,9 +1022,16 @@ bool nr_timer_tick(NR_timer_t *timer)
 
 bool nr_timer_expired(NR_timer_t timer)
 {
+  if (timer.target == UINT_MAX) // infinite target, never expires
+    return false;
   return (timer.counter >= timer.target);
 }
 
+uint32_t nr_timer_elapsed_time(NR_timer_t timer)
+{
+  return timer.counter;
+}
+
 void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step)
 {
   timer->target = target;
diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h
index c76969a8e89e83904b027fe20dbfc0e582bf9a35..4a90d79578d4944cd6bbbed0b80d3374853b7c2e 100644
--- a/common/utils/nr/nr_common.h
+++ b/common/utils/nr/nr_common.h
@@ -158,6 +158,13 @@ bool nr_timer_expired(NR_timer_t timer);
  * @return Indication if the timer is active or not
  */
 bool is_nr_timer_active(NR_timer_t timer);
+/**
+ * @brief To return how much time has passed since start of timer
+ * @param timer Timer to be checked
+ * @return Time passed since start of timer
+ */
+uint32_t nr_timer_elapsed_time(NR_timer_t timer);
+
 
 extern const nr_bandentry_t nr_bandtable[];
 
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index ef5df5beb9ef690286dbc517b0e23c681eff405d..c86aad9ab26898342e4df321cb3e87f810ee105c 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -657,10 +657,70 @@ static int nr_get_ms_bucketsizeduration(long bucketsizeduration)
   }
 }
 
+static uint32_t nr_get_pbr(long prioritizedbitrate)  // returns Bps
+{
+  uint32_t pbr = 0;
+  switch (prioritizedbitrate) {
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps0:
+      pbr = 0;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8:
+      pbr = 8;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16:
+      pbr = 16;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32:
+      pbr = 32;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps64:
+      pbr = 64;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps128:
+      pbr = 128;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps256:
+      pbr = 256;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps512:
+      pbr = 512;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps1024:
+      pbr = 1024;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps2048:
+      pbr = 2048;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps4096:
+      pbr = 4096;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8192:
+      pbr = 8192;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16384:
+      pbr = 16384;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32768:
+      pbr = 32768;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps65536:
+      pbr = 65536;
+      break;
+    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity:
+      pbr = UINT_MAX;
+      break;
+    default:
+      AssertFatal(false, "The proritized bit rate value is not one of the enum values\n");
+  }
+  uint32_t pbr_bytes =
+      (prioritizedbitrate < NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) ? pbr * 1000 : pbr;
+  return pbr_bytes;
+}
+
 static uint32_t get_lc_bucket_size(long prioritisedBitRate, long bucketSizeDuration)
 {
-  int pbr = nr_get_pbr(prioritisedBitRate);
-  // in infinite pbr, the bucket is saturated by pbr
+  uint32_t pbr = nr_get_pbr(prioritisedBitRate);
+  // if infinite pbr, the bucket is saturated by pbr
   int bsd = 0;
   if (prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity)
     bsd = 1;
@@ -675,8 +735,8 @@ static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SR
 {
   lc_info->lcid = srb_id;
   lc_info->priority = srb_id == 2 ? 3 : 1;
-  lc_info->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
-  lc_info->bucket_size = get_lc_bucket_size(lc_info->prioritisedBitRate, 0);
+  lc_info->pbr = UINT_MAX;
+  lc_info->bucket_size = UINT_MAX;
 }
 
 static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac,
@@ -693,10 +753,14 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac,
   AssertFatal(mac_lc_config->ul_SpecificParameters, "UL parameters shouldn't be NULL for DRBs\n");
   struct NR_LogicalChannelConfig__ul_SpecificParameters *ul_parm = mac_lc_config->ul_SpecificParameters;
   lc_info->priority = ul_parm->priority;
-  lc_info->prioritisedBitRate = ul_parm->prioritisedBitRate;
+  lc_info->pbr = nr_get_pbr(ul_parm->prioritisedBitRate);
   // TODO Verify setting to 0 is ok, 331 just says need R (release if NULL)
   mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].LCGID = ul_parm->logicalChannelGroup ? *ul_parm->logicalChannelGroup : 0;
   lc_info->bucket_size = get_lc_bucket_size(ul_parm->prioritisedBitRate, ul_parm->bucketSizeDuration);
+  // setup and start Bj timer for this LC
+  NR_timer_t *bjt = &mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].Bj_timer;
+  nr_timer_setup(bjt, UINT_MAX, 1);  // this timer never expires in principle, counter incremented by number of slots
+  nr_timer_start(bjt);
 }
 
 static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac,
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 0c112ac66d34551baf8205efea0f7b8775a30c63..97c1860d1b2fefef632a9bb46f2dc4ecfe157689 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -185,6 +185,7 @@ typedef struct {
   long LCGID;
   // Bj bucket usage per lcid
   int32_t Bj;
+  NR_timer_t Bj_timer;
 } NR_LC_SCHEDULING_INFO;
 
 typedef struct {
@@ -441,7 +442,7 @@ typedef struct nr_lcordered_info_s {
   // logical channels ids ordered as per priority
   NR_LogicalChannelIdentity_t lcid;
   long priority;
-  long prioritisedBitRate;
+  uint32_t pbr; // in B/s (UINT_MAX = infinite)
   // Bucket size per lcid
   uint32_t bucket_size;
 } nr_lcordered_info_t;
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index 7322024e7b5fc378d9f2263f8d7973f76c62a512..e3d887f2a35ef51c324998c915ec99134edb3872 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -138,13 +138,6 @@ bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t
 uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size,
                                     int value);
 
-/*! \fn  int nr_get_pbr(long prioritizedbitrate)
-   \brief get the rate in kbps from the rate configured by the higher layer
-\param[in]  prioritizedbitrate
-\return the rate in kbps
-*/
-uint32_t nr_get_pbr(long prioritizedbitrate);
-
 /*! \fn  int nr_get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer)
    \brief get the number of subframe from the periodic BSR timer configured by the higher layers
 \param[in] periodicBSR_Timer timer for periodic BSR
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index 4bd1e29ca9da9af7d4056a2b88c825a9a7808d30..bfded89c1565a7989721bd2631cabf0f3728b69c 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -118,6 +118,10 @@ static NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *ma
 void update_mac_timers(NR_UE_MAC_INST_t *mac)
 {
   nr_timer_tick(&mac->ra.contention_resolution_timer);
+  for (int i = 0; i < NR_MAX_NUM_LCID; i++)
+    AssertFatal(!nr_timer_tick(&mac->scheduling_info.lc_sched_info[i].Bj_timer),
+                "Bj timer for LCID %d expired! That should never happen\n",
+                i);
 }
 
 void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu)
@@ -1150,22 +1154,27 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
     nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
     int lcid = lc_info->lcid;
     // max amount of data that can be buffered/accumulated in a logical channel buffer
-    int32_t bucketSize_max = lc_info->bucket_size;
-    AssertFatal(bucketSize_max >= 0, "negative bucketSize_max %d, will never schedule UE: lcid %d\n",bucketSize_max, lcid);
+    uint32_t bucketSize_max = lc_info->bucket_size;
 
     /*
       measure Bj
       increment the value of Bj by product PBR  * T
     */
     NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
-    int T = 1; // time elapsed since Bj was last incremented
     int32_t bj = sched_info->Bj;
-    bj += nr_get_pbr(lc_info->prioritisedBitRate) * T;
-    if (lc_info->prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity)
-      bj = nr_get_pbr(lc_info->prioritisedBitRate);
+    if (lc_info->pbr < UINT_MAX) {
+      uint32_t slots_elapsed = nr_timer_elapsed_time(sched_info->Bj_timer); // slots elapsed since Bj was last incremented
+      // it is safe to divide by 1k since pbr in lc_info is computed multiplying by 1000 the RRC value to convert kB/s to B/s
+      uint32_t pbr_ms = lc_info->pbr / 1000;
+      bj += ((pbr_ms * slots_elapsed) >> mac->current_UL_BWP->scs); // each slot length is 1/scs ms
+    }
+    else
+      bj = INT_MAX;
 
     // bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization
     sched_info->Bj = min(bj, bucketSize_max);
+    // reset bj timer
+    nr_timer_start(&sched_info->Bj_timer);
   }
 
   // Call BSR procedure as described in Section 5.4.5 in 38.321
@@ -2883,7 +2892,7 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
   /* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/
   nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, lc_num);
   AssertFatal(lc_info, "Couldn't find logical channel with LCID %d\n", lc_num);
-  uint32_t pbr = nr_get_pbr(lc_info->prioritisedBitRate);
+  uint32_t pbr = lc_info->pbr;
   NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lc_num);
   int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain;
   *target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr;
@@ -3132,8 +3141,8 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
   bool lcids_data_status[NR_MAX_NUM_LCID] = {0};
   memset(lcids_data_status, 1, NR_MAX_NUM_LCID);
 
-  uint32_t lcp_allocation_counter =
-      0; // in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider
+  // in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider
+  uint32_t lcp_allocation_counter = 0;
   // bj and prioritized bit rate but just consider priority
   uint16_t buflen_ep = 0; // this variable holds the length in bytes in mac pdu when multiple equal priority channels are present
   // because as per standard(TS38.321), all equal priority channels should be served equally
@@ -3300,80 +3309,3 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TI
   dl_config->number_pdus += 1;
   ul_time_alignment->ta_apply = no_ta;
 }
-
-uint32_t nr_get_pbr(long prioritizedbitrate)
-{
-  int32_t pbr = -1;
-  switch (prioritizedbitrate) {
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps0:
-      pbr = 0;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8:
-      pbr = 8;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16:
-      pbr = 16;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32:
-      pbr = 32;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps64:
-      pbr = 64;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps128:
-      pbr = 128;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps256:
-      pbr = 256;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps512:
-      pbr = 512;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps1024:
-      pbr = 1024;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps2048:
-      pbr = 2048;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps4096:
-      pbr = 4096;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8192:
-      pbr = 8192;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16384:
-      pbr = 16384;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32768:
-      pbr = 32768;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps65536:
-      pbr = 65536;
-      break;
-
-    case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity:
-      pbr = INT32_MAX;
-      break;
-
-    default:
-      pbr = -1;
-  }
-  AssertFatal(pbr >= 0, "The proritized bit rate value is not one of the enum values\n");
-  uint32_t pbr_bytes =
-      (prioritizedbitrate < NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) ? pbr * 1000 : pbr;
-  return pbr_bytes;
-}